transport.py 119 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135
  1. # Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
  2. # Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
  3. #
  4. # This file is part of paramiko.
  5. #
  6. # Paramiko is free software; you can redistribute it and/or modify it under the
  7. # terms of the GNU Lesser General Public License as published by the Free
  8. # Software Foundation; either version 2.1 of the License, or (at your option)
  9. # any later version.
  10. #
  11. # Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
  12. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  13. # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  14. # details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License
  17. # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
  18. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. """
  20. Core protocol implementation
  21. """
  22. from __future__ import print_function
  23. import os
  24. import socket
  25. import sys
  26. import threading
  27. import time
  28. import weakref
  29. from hashlib import md5, sha1, sha256, sha512
  30. from cryptography.hazmat.backends import default_backend
  31. from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
  32. import paramiko
  33. from paramiko import util
  34. from paramiko.auth_handler import AuthHandler
  35. from paramiko.ssh_gss import GSSAuth
  36. from paramiko.channel import Channel
  37. from paramiko.common import (
  38. xffffffff,
  39. cMSG_CHANNEL_OPEN,
  40. cMSG_IGNORE,
  41. cMSG_GLOBAL_REQUEST,
  42. DEBUG,
  43. MSG_KEXINIT,
  44. MSG_IGNORE,
  45. MSG_DISCONNECT,
  46. MSG_DEBUG,
  47. ERROR,
  48. WARNING,
  49. cMSG_UNIMPLEMENTED,
  50. INFO,
  51. cMSG_KEXINIT,
  52. cMSG_NEWKEYS,
  53. MSG_NEWKEYS,
  54. cMSG_REQUEST_SUCCESS,
  55. cMSG_REQUEST_FAILURE,
  56. CONNECTION_FAILED_CODE,
  57. OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED,
  58. OPEN_SUCCEEDED,
  59. cMSG_CHANNEL_OPEN_FAILURE,
  60. cMSG_CHANNEL_OPEN_SUCCESS,
  61. MSG_GLOBAL_REQUEST,
  62. MSG_REQUEST_SUCCESS,
  63. MSG_REQUEST_FAILURE,
  64. MSG_CHANNEL_OPEN_SUCCESS,
  65. MSG_CHANNEL_OPEN_FAILURE,
  66. MSG_CHANNEL_OPEN,
  67. MSG_CHANNEL_SUCCESS,
  68. MSG_CHANNEL_FAILURE,
  69. MSG_CHANNEL_DATA,
  70. MSG_CHANNEL_EXTENDED_DATA,
  71. MSG_CHANNEL_WINDOW_ADJUST,
  72. MSG_CHANNEL_REQUEST,
  73. MSG_CHANNEL_EOF,
  74. MSG_CHANNEL_CLOSE,
  75. MIN_WINDOW_SIZE,
  76. MIN_PACKET_SIZE,
  77. MAX_WINDOW_SIZE,
  78. DEFAULT_WINDOW_SIZE,
  79. DEFAULT_MAX_PACKET_SIZE,
  80. HIGHEST_USERAUTH_MESSAGE_ID,
  81. MSG_UNIMPLEMENTED,
  82. MSG_NAMES,
  83. MSG_EXT_INFO,
  84. cMSG_EXT_INFO,
  85. )
  86. from paramiko.compress import ZlibCompressor, ZlibDecompressor
  87. from paramiko.dsskey import DSSKey
  88. from paramiko.ed25519key import Ed25519Key
  89. from paramiko.kex_curve25519 import KexCurve25519
  90. from paramiko.kex_gex import KexGex, KexGexSHA256
  91. from paramiko.kex_group1 import KexGroup1
  92. from paramiko.kex_group14 import KexGroup14, KexGroup14SHA256
  93. from paramiko.kex_group16 import KexGroup16SHA512
  94. from paramiko.kex_ecdh_nist import KexNistp256, KexNistp384, KexNistp521
  95. from paramiko.kex_gss import KexGSSGex, KexGSSGroup1, KexGSSGroup14
  96. from paramiko.message import Message
  97. from paramiko.packet import Packetizer, NeedRekeyException
  98. from paramiko.primes import ModulusPack
  99. from paramiko.py3compat import string_types, long, byte_ord, b, input, PY2
  100. from paramiko.rsakey import RSAKey
  101. from paramiko.ecdsakey import ECDSAKey
  102. from paramiko.server import ServerInterface
  103. from paramiko.sftp_client import SFTPClient
  104. from paramiko.ssh_exception import (
  105. SSHException,
  106. BadAuthenticationType,
  107. ChannelException,
  108. IncompatiblePeer,
  109. ProxyCommandFailure,
  110. )
  111. from paramiko.util import retry_on_signal, ClosingContextManager, clamp_value
  112. # for thread cleanup
  113. _active_threads = []
  114. def _join_lingering_threads():
  115. for thr in _active_threads:
  116. thr.stop_thread()
  117. import atexit
  118. atexit.register(_join_lingering_threads)
  119. class Transport(threading.Thread, ClosingContextManager):
  120. """
  121. An SSH Transport attaches to a stream (usually a socket), negotiates an
  122. encrypted session, authenticates, and then creates stream tunnels, called
  123. `channels <.Channel>`, across the session. Multiple channels can be
  124. multiplexed across a single session (and often are, in the case of port
  125. forwardings).
  126. Instances of this class may be used as context managers.
  127. """
  128. _ENCRYPT = object()
  129. _DECRYPT = object()
  130. _PROTO_ID = "2.0"
  131. _CLIENT_ID = "paramiko_{}".format(paramiko.__version__)
  132. # These tuples of algorithm identifiers are in preference order; do not
  133. # reorder without reason!
  134. # NOTE: if you need to modify these, we suggest leveraging the
  135. # `disabled_algorithms` constructor argument (also available in SSHClient)
  136. # instead of monkeypatching or subclassing.
  137. _preferred_ciphers = (
  138. "aes128-ctr",
  139. "aes192-ctr",
  140. "aes256-ctr",
  141. "aes128-cbc",
  142. "aes192-cbc",
  143. "aes256-cbc",
  144. "3des-cbc",
  145. )
  146. _preferred_macs = (
  147. "hmac-sha2-256",
  148. "hmac-sha2-512",
  149. "hmac-sha2-256-etm@openssh.com",
  150. "hmac-sha2-512-etm@openssh.com",
  151. "hmac-sha1",
  152. "hmac-md5",
  153. "hmac-sha1-96",
  154. "hmac-md5-96",
  155. )
  156. # ~= HostKeyAlgorithms in OpenSSH land
  157. _preferred_keys = (
  158. "ssh-ed25519",
  159. "ecdsa-sha2-nistp256",
  160. "ecdsa-sha2-nistp384",
  161. "ecdsa-sha2-nistp521",
  162. "rsa-sha2-512",
  163. "rsa-sha2-256",
  164. "ssh-rsa",
  165. "ssh-dss",
  166. )
  167. # ~= PubKeyAcceptedAlgorithms
  168. _preferred_pubkeys = (
  169. "ssh-ed25519",
  170. "ecdsa-sha2-nistp256",
  171. "ecdsa-sha2-nistp384",
  172. "ecdsa-sha2-nistp521",
  173. "rsa-sha2-512",
  174. "rsa-sha2-256",
  175. "ssh-rsa",
  176. "ssh-dss",
  177. )
  178. _preferred_kex = (
  179. "ecdh-sha2-nistp256",
  180. "ecdh-sha2-nistp384",
  181. "ecdh-sha2-nistp521",
  182. "diffie-hellman-group16-sha512",
  183. "diffie-hellman-group-exchange-sha256",
  184. "diffie-hellman-group14-sha256",
  185. "diffie-hellman-group-exchange-sha1",
  186. "diffie-hellman-group14-sha1",
  187. "diffie-hellman-group1-sha1",
  188. )
  189. if KexCurve25519.is_available():
  190. _preferred_kex = ("curve25519-sha256@libssh.org",) + _preferred_kex
  191. _preferred_gsskex = (
  192. "gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==",
  193. "gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==",
  194. "gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==",
  195. )
  196. _preferred_compression = ("none",)
  197. _cipher_info = {
  198. "aes128-ctr": {
  199. "class": algorithms.AES,
  200. "mode": modes.CTR,
  201. "block-size": 16,
  202. "key-size": 16,
  203. },
  204. "aes192-ctr": {
  205. "class": algorithms.AES,
  206. "mode": modes.CTR,
  207. "block-size": 16,
  208. "key-size": 24,
  209. },
  210. "aes256-ctr": {
  211. "class": algorithms.AES,
  212. "mode": modes.CTR,
  213. "block-size": 16,
  214. "key-size": 32,
  215. },
  216. "aes128-cbc": {
  217. "class": algorithms.AES,
  218. "mode": modes.CBC,
  219. "block-size": 16,
  220. "key-size": 16,
  221. },
  222. "aes192-cbc": {
  223. "class": algorithms.AES,
  224. "mode": modes.CBC,
  225. "block-size": 16,
  226. "key-size": 24,
  227. },
  228. "aes256-cbc": {
  229. "class": algorithms.AES,
  230. "mode": modes.CBC,
  231. "block-size": 16,
  232. "key-size": 32,
  233. },
  234. "3des-cbc": {
  235. "class": algorithms.TripleDES,
  236. "mode": modes.CBC,
  237. "block-size": 8,
  238. "key-size": 24,
  239. },
  240. }
  241. _mac_info = {
  242. "hmac-sha1": {"class": sha1, "size": 20},
  243. "hmac-sha1-96": {"class": sha1, "size": 12},
  244. "hmac-sha2-256": {"class": sha256, "size": 32},
  245. "hmac-sha2-256-etm@openssh.com": {"class": sha256, "size": 32},
  246. "hmac-sha2-512": {"class": sha512, "size": 64},
  247. "hmac-sha2-512-etm@openssh.com": {"class": sha512, "size": 64},
  248. "hmac-md5": {"class": md5, "size": 16},
  249. "hmac-md5-96": {"class": md5, "size": 12},
  250. }
  251. _key_info = {
  252. # TODO: at some point we will want to drop this as it's no longer
  253. # considered secure due to using SHA-1 for signatures. OpenSSH 8.8 no
  254. # longer supports it. Question becomes at what point do we want to
  255. # prevent users with older setups from using this?
  256. "ssh-rsa": RSAKey,
  257. "ssh-rsa-cert-v01@openssh.com": RSAKey,
  258. "rsa-sha2-256": RSAKey,
  259. "rsa-sha2-256-cert-v01@openssh.com": RSAKey,
  260. "rsa-sha2-512": RSAKey,
  261. "rsa-sha2-512-cert-v01@openssh.com": RSAKey,
  262. "ssh-dss": DSSKey,
  263. "ssh-dss-cert-v01@openssh.com": DSSKey,
  264. "ecdsa-sha2-nistp256": ECDSAKey,
  265. "ecdsa-sha2-nistp256-cert-v01@openssh.com": ECDSAKey,
  266. "ecdsa-sha2-nistp384": ECDSAKey,
  267. "ecdsa-sha2-nistp384-cert-v01@openssh.com": ECDSAKey,
  268. "ecdsa-sha2-nistp521": ECDSAKey,
  269. "ecdsa-sha2-nistp521-cert-v01@openssh.com": ECDSAKey,
  270. "ssh-ed25519": Ed25519Key,
  271. "ssh-ed25519-cert-v01@openssh.com": Ed25519Key,
  272. }
  273. _kex_info = {
  274. "diffie-hellman-group1-sha1": KexGroup1,
  275. "diffie-hellman-group14-sha1": KexGroup14,
  276. "diffie-hellman-group-exchange-sha1": KexGex,
  277. "diffie-hellman-group-exchange-sha256": KexGexSHA256,
  278. "diffie-hellman-group14-sha256": KexGroup14SHA256,
  279. "diffie-hellman-group16-sha512": KexGroup16SHA512,
  280. "gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGroup1,
  281. "gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGroup14,
  282. "gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==": KexGSSGex,
  283. "ecdh-sha2-nistp256": KexNistp256,
  284. "ecdh-sha2-nistp384": KexNistp384,
  285. "ecdh-sha2-nistp521": KexNistp521,
  286. }
  287. if KexCurve25519.is_available():
  288. _kex_info["curve25519-sha256@libssh.org"] = KexCurve25519
  289. _compression_info = {
  290. # zlib@openssh.com is just zlib, but only turned on after a successful
  291. # authentication. openssh servers may only offer this type because
  292. # they've had troubles with security holes in zlib in the past.
  293. "zlib@openssh.com": (ZlibCompressor, ZlibDecompressor),
  294. "zlib": (ZlibCompressor, ZlibDecompressor),
  295. "none": (None, None),
  296. }
  297. _modulus_pack = None
  298. _active_check_timeout = 0.1
  299. def __init__(
  300. self,
  301. sock,
  302. default_window_size=DEFAULT_WINDOW_SIZE,
  303. default_max_packet_size=DEFAULT_MAX_PACKET_SIZE,
  304. gss_kex=False,
  305. gss_deleg_creds=True,
  306. disabled_algorithms=None,
  307. server_sig_algs=True,
  308. ):
  309. """
  310. Create a new SSH session over an existing socket, or socket-like
  311. object. This only creates the `.Transport` object; it doesn't begin
  312. the SSH session yet. Use `connect` or `start_client` to begin a client
  313. session, or `start_server` to begin a server session.
  314. If the object is not actually a socket, it must have the following
  315. methods:
  316. - ``send(str)``: Writes from 1 to ``len(str)`` bytes, and returns an
  317. int representing the number of bytes written. Returns
  318. 0 or raises ``EOFError`` if the stream has been closed.
  319. - ``recv(int)``: Reads from 1 to ``int`` bytes and returns them as a
  320. string. Returns 0 or raises ``EOFError`` if the stream has been
  321. closed.
  322. - ``close()``: Closes the socket.
  323. - ``settimeout(n)``: Sets a (float) timeout on I/O operations.
  324. For ease of use, you may also pass in an address (as a tuple) or a host
  325. string as the ``sock`` argument. (A host string is a hostname with an
  326. optional port (separated by ``":"``) which will be converted into a
  327. tuple of ``(hostname, port)``.) A socket will be connected to this
  328. address and used for communication. Exceptions from the ``socket``
  329. call may be thrown in this case.
  330. .. note::
  331. Modifying the the window and packet sizes might have adverse
  332. effects on your channels created from this transport. The default
  333. values are the same as in the OpenSSH code base and have been
  334. battle tested.
  335. :param socket sock:
  336. a socket or socket-like object to create the session over.
  337. :param int default_window_size:
  338. sets the default window size on the transport. (defaults to
  339. 2097152)
  340. :param int default_max_packet_size:
  341. sets the default max packet size on the transport. (defaults to
  342. 32768)
  343. :param bool gss_kex:
  344. Whether to enable GSSAPI key exchange when GSSAPI is in play.
  345. Default: ``False``.
  346. :param bool gss_deleg_creds:
  347. Whether to enable GSSAPI credential delegation when GSSAPI is in
  348. play. Default: ``True``.
  349. :param dict disabled_algorithms:
  350. If given, must be a dictionary mapping algorithm type to an
  351. iterable of algorithm identifiers, which will be disabled for the
  352. lifetime of the transport.
  353. Keys should match the last word in the class' builtin algorithm
  354. tuple attributes, such as ``"ciphers"`` to disable names within
  355. ``_preferred_ciphers``; or ``"kex"`` to disable something defined
  356. inside ``_preferred_kex``. Values should exactly match members of
  357. the matching attribute.
  358. For example, if you need to disable
  359. ``diffie-hellman-group16-sha512`` key exchange (perhaps because
  360. your code talks to a server which implements it differently from
  361. Paramiko), specify ``disabled_algorithms={"kex":
  362. ["diffie-hellman-group16-sha512"]}``.
  363. :param bool server_sig_algs:
  364. Whether to send an extra message to compatible clients, in server
  365. mode, with a list of supported pubkey algorithms. Default:
  366. ``True``.
  367. .. versionchanged:: 1.15
  368. Added the ``default_window_size`` and ``default_max_packet_size``
  369. arguments.
  370. .. versionchanged:: 1.15
  371. Added the ``gss_kex`` and ``gss_deleg_creds`` kwargs.
  372. .. versionchanged:: 2.6
  373. Added the ``disabled_algorithms`` kwarg.
  374. .. versionchanged:: 2.9
  375. Added the ``server_sig_algs`` kwarg.
  376. """
  377. self.active = False
  378. self.hostname = None
  379. self.server_extensions = {}
  380. if isinstance(sock, string_types):
  381. # convert "host:port" into (host, port)
  382. hl = sock.split(":", 1)
  383. self.hostname = hl[0]
  384. if len(hl) == 1:
  385. sock = (hl[0], 22)
  386. else:
  387. sock = (hl[0], int(hl[1]))
  388. if type(sock) is tuple:
  389. # connect to the given (host, port)
  390. hostname, port = sock
  391. self.hostname = hostname
  392. reason = "No suitable address family"
  393. addrinfos = socket.getaddrinfo(
  394. hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM
  395. )
  396. for family, socktype, proto, canonname, sockaddr in addrinfos:
  397. if socktype == socket.SOCK_STREAM:
  398. af = family
  399. # addr = sockaddr
  400. sock = socket.socket(af, socket.SOCK_STREAM)
  401. try:
  402. retry_on_signal(lambda: sock.connect((hostname, port)))
  403. except socket.error as e:
  404. reason = str(e)
  405. else:
  406. break
  407. else:
  408. raise SSHException(
  409. "Unable to connect to {}: {}".format(hostname, reason)
  410. )
  411. # okay, normal socket-ish flow here...
  412. threading.Thread.__init__(self)
  413. self.daemon = True
  414. self.sock = sock
  415. # we set the timeout so we can check self.active periodically to
  416. # see if we should bail. socket.timeout exception is never propagated.
  417. self.sock.settimeout(self._active_check_timeout)
  418. # negotiated crypto parameters
  419. self.packetizer = Packetizer(sock)
  420. self.local_version = "SSH-" + self._PROTO_ID + "-" + self._CLIENT_ID
  421. self.remote_version = ""
  422. self.local_cipher = self.remote_cipher = ""
  423. self.local_kex_init = self.remote_kex_init = None
  424. self.local_mac = self.remote_mac = None
  425. self.local_compression = self.remote_compression = None
  426. self.session_id = None
  427. self.host_key_type = None
  428. self.host_key = None
  429. # GSS-API / SSPI Key Exchange
  430. self.use_gss_kex = gss_kex
  431. # This will be set to True if GSS-API Key Exchange was performed
  432. self.gss_kex_used = False
  433. self.kexgss_ctxt = None
  434. self.gss_host = None
  435. if self.use_gss_kex:
  436. self.kexgss_ctxt = GSSAuth("gssapi-keyex", gss_deleg_creds)
  437. self._preferred_kex = self._preferred_gsskex + self._preferred_kex
  438. # state used during negotiation
  439. self.kex_engine = None
  440. self.H = None
  441. self.K = None
  442. self.initial_kex_done = False
  443. self.in_kex = False
  444. self.authenticated = False
  445. self._expected_packet = tuple()
  446. # synchronization (always higher level than write_lock)
  447. self.lock = threading.Lock()
  448. # tracking open channels
  449. self._channels = ChannelMap()
  450. self.channel_events = {} # (id -> Event)
  451. self.channels_seen = {} # (id -> True)
  452. self._channel_counter = 0
  453. self.default_max_packet_size = default_max_packet_size
  454. self.default_window_size = default_window_size
  455. self._forward_agent_handler = None
  456. self._x11_handler = None
  457. self._tcp_handler = None
  458. self.saved_exception = None
  459. self.clear_to_send = threading.Event()
  460. self.clear_to_send_lock = threading.Lock()
  461. self.clear_to_send_timeout = 30.0
  462. self.log_name = "paramiko.transport"
  463. self.logger = util.get_logger(self.log_name)
  464. self.packetizer.set_log(self.logger)
  465. self.auth_handler = None
  466. # response Message from an arbitrary global request
  467. self.global_response = None
  468. # user-defined event callbacks
  469. self.completion_event = None
  470. # how long (seconds) to wait for the SSH banner
  471. self.banner_timeout = 15
  472. # how long (seconds) to wait for the handshake to finish after SSH
  473. # banner sent.
  474. self.handshake_timeout = 15
  475. # how long (seconds) to wait for the auth response.
  476. self.auth_timeout = 30
  477. self.disabled_algorithms = disabled_algorithms or {}
  478. self.server_sig_algs = server_sig_algs
  479. # server mode:
  480. self.server_mode = False
  481. self.server_object = None
  482. self.server_key_dict = {}
  483. self.server_accepts = []
  484. self.server_accept_cv = threading.Condition(self.lock)
  485. self.subsystem_table = {}
  486. def _filter_algorithm(self, type_):
  487. default = getattr(self, "_preferred_{}".format(type_))
  488. return tuple(
  489. x
  490. for x in default
  491. if x not in self.disabled_algorithms.get(type_, [])
  492. )
  493. @property
  494. def preferred_ciphers(self):
  495. return self._filter_algorithm("ciphers")
  496. @property
  497. def preferred_macs(self):
  498. return self._filter_algorithm("macs")
  499. @property
  500. def preferred_keys(self):
  501. # Interleave cert variants here; resistant to various background
  502. # overwriting of _preferred_keys, and necessary as hostkeys can't use
  503. # the logic pubkey auth does re: injecting/checking for certs at
  504. # runtime
  505. filtered = self._filter_algorithm("keys")
  506. return tuple(
  507. filtered
  508. + tuple("{}-cert-v01@openssh.com".format(x) for x in filtered)
  509. )
  510. @property
  511. def preferred_pubkeys(self):
  512. return self._filter_algorithm("pubkeys")
  513. @property
  514. def preferred_kex(self):
  515. return self._filter_algorithm("kex")
  516. @property
  517. def preferred_compression(self):
  518. return self._filter_algorithm("compression")
  519. def __repr__(self):
  520. """
  521. Returns a string representation of this object, for debugging.
  522. """
  523. id_ = hex(long(id(self)) & xffffffff)
  524. out = "<paramiko.Transport at {}".format(id_)
  525. if not self.active:
  526. out += " (unconnected)"
  527. else:
  528. if self.local_cipher != "":
  529. out += " (cipher {}, {:d} bits)".format(
  530. self.local_cipher,
  531. self._cipher_info[self.local_cipher]["key-size"] * 8,
  532. )
  533. if self.is_authenticated():
  534. out += " (active; {} open channel(s))".format(
  535. len(self._channels)
  536. )
  537. elif self.initial_kex_done:
  538. out += " (connected; awaiting auth)"
  539. else:
  540. out += " (connecting)"
  541. out += ">"
  542. return out
  543. def atfork(self):
  544. """
  545. Terminate this Transport without closing the session. On posix
  546. systems, if a Transport is open during process forking, both parent
  547. and child will share the underlying socket, but only one process can
  548. use the connection (without corrupting the session). Use this method
  549. to clean up a Transport object without disrupting the other process.
  550. .. versionadded:: 1.5.3
  551. """
  552. self.sock.close()
  553. self.close()
  554. def get_security_options(self):
  555. """
  556. Return a `.SecurityOptions` object which can be used to tweak the
  557. encryption algorithms this transport will permit (for encryption,
  558. digest/hash operations, public keys, and key exchanges) and the order
  559. of preference for them.
  560. """
  561. return SecurityOptions(self)
  562. def set_gss_host(self, gss_host, trust_dns=True, gssapi_requested=True):
  563. """
  564. Normalize/canonicalize ``self.gss_host`` depending on various factors.
  565. :param str gss_host:
  566. The explicitly requested GSS-oriented hostname to connect to (i.e.
  567. what the host's name is in the Kerberos database.) Defaults to
  568. ``self.hostname`` (which will be the 'real' target hostname and/or
  569. host portion of given socket object.)
  570. :param bool trust_dns:
  571. Indicates whether or not DNS is trusted; if true, DNS will be used
  572. to canonicalize the GSS hostname (which again will either be
  573. ``gss_host`` or the transport's default hostname.)
  574. (Defaults to True due to backwards compatibility.)
  575. :param bool gssapi_requested:
  576. Whether GSSAPI key exchange or authentication was even requested.
  577. If not, this is a no-op and nothing happens
  578. (and ``self.gss_host`` is not set.)
  579. (Defaults to True due to backwards compatibility.)
  580. :returns: ``None``.
  581. """
  582. # No GSSAPI in play == nothing to do
  583. if not gssapi_requested:
  584. return
  585. # Obtain the correct host first - did user request a GSS-specific name
  586. # to use that is distinct from the actual SSH target hostname?
  587. if gss_host is None:
  588. gss_host = self.hostname
  589. # Finally, canonicalize via DNS if DNS is trusted.
  590. if trust_dns and gss_host is not None:
  591. gss_host = socket.getfqdn(gss_host)
  592. # And set attribute for reference later.
  593. self.gss_host = gss_host
  594. def start_client(self, event=None, timeout=None):
  595. """
  596. Negotiate a new SSH2 session as a client. This is the first step after
  597. creating a new `.Transport`. A separate thread is created for protocol
  598. negotiation.
  599. If an event is passed in, this method returns immediately. When
  600. negotiation is done (successful or not), the given ``Event`` will
  601. be triggered. On failure, `is_active` will return ``False``.
  602. (Since 1.4) If ``event`` is ``None``, this method will not return until
  603. negotiation is done. On success, the method returns normally.
  604. Otherwise an SSHException is raised.
  605. After a successful negotiation, you will usually want to authenticate,
  606. calling `auth_password <Transport.auth_password>` or
  607. `auth_publickey <Transport.auth_publickey>`.
  608. .. note:: `connect` is a simpler method for connecting as a client.
  609. .. note::
  610. After calling this method (or `start_server` or `connect`), you
  611. should no longer directly read from or write to the original socket
  612. object.
  613. :param .threading.Event event:
  614. an event to trigger when negotiation is complete (optional)
  615. :param float timeout:
  616. a timeout, in seconds, for SSH2 session negotiation (optional)
  617. :raises:
  618. `.SSHException` -- if negotiation fails (and no ``event`` was
  619. passed in)
  620. """
  621. self.active = True
  622. if event is not None:
  623. # async, return immediately and let the app poll for completion
  624. self.completion_event = event
  625. self.start()
  626. return
  627. # synchronous, wait for a result
  628. self.completion_event = event = threading.Event()
  629. self.start()
  630. max_time = time.time() + timeout if timeout is not None else None
  631. while True:
  632. event.wait(0.1)
  633. if not self.active:
  634. e = self.get_exception()
  635. if e is not None:
  636. raise e
  637. raise SSHException("Negotiation failed.")
  638. if event.is_set() or (
  639. timeout is not None and time.time() >= max_time
  640. ):
  641. break
  642. def start_server(self, event=None, server=None):
  643. """
  644. Negotiate a new SSH2 session as a server. This is the first step after
  645. creating a new `.Transport` and setting up your server host key(s). A
  646. separate thread is created for protocol negotiation.
  647. If an event is passed in, this method returns immediately. When
  648. negotiation is done (successful or not), the given ``Event`` will
  649. be triggered. On failure, `is_active` will return ``False``.
  650. (Since 1.4) If ``event`` is ``None``, this method will not return until
  651. negotiation is done. On success, the method returns normally.
  652. Otherwise an SSHException is raised.
  653. After a successful negotiation, the client will need to authenticate.
  654. Override the methods `get_allowed_auths
  655. <.ServerInterface.get_allowed_auths>`, `check_auth_none
  656. <.ServerInterface.check_auth_none>`, `check_auth_password
  657. <.ServerInterface.check_auth_password>`, and `check_auth_publickey
  658. <.ServerInterface.check_auth_publickey>` in the given ``server`` object
  659. to control the authentication process.
  660. After a successful authentication, the client should request to open a
  661. channel. Override `check_channel_request
  662. <.ServerInterface.check_channel_request>` in the given ``server``
  663. object to allow channels to be opened.
  664. .. note::
  665. After calling this method (or `start_client` or `connect`), you
  666. should no longer directly read from or write to the original socket
  667. object.
  668. :param .threading.Event event:
  669. an event to trigger when negotiation is complete.
  670. :param .ServerInterface server:
  671. an object used to perform authentication and create `channels
  672. <.Channel>`
  673. :raises:
  674. `.SSHException` -- if negotiation fails (and no ``event`` was
  675. passed in)
  676. """
  677. if server is None:
  678. server = ServerInterface()
  679. self.server_mode = True
  680. self.server_object = server
  681. self.active = True
  682. if event is not None:
  683. # async, return immediately and let the app poll for completion
  684. self.completion_event = event
  685. self.start()
  686. return
  687. # synchronous, wait for a result
  688. self.completion_event = event = threading.Event()
  689. self.start()
  690. while True:
  691. event.wait(0.1)
  692. if not self.active:
  693. e = self.get_exception()
  694. if e is not None:
  695. raise e
  696. raise SSHException("Negotiation failed.")
  697. if event.is_set():
  698. break
  699. def add_server_key(self, key):
  700. """
  701. Add a host key to the list of keys used for server mode. When behaving
  702. as a server, the host key is used to sign certain packets during the
  703. SSH2 negotiation, so that the client can trust that we are who we say
  704. we are. Because this is used for signing, the key must contain private
  705. key info, not just the public half. Only one key of each type (RSA or
  706. DSS) is kept.
  707. :param .PKey key:
  708. the host key to add, usually an `.RSAKey` or `.DSSKey`.
  709. """
  710. self.server_key_dict[key.get_name()] = key
  711. # Handle SHA-2 extensions for RSA by ensuring that lookups into
  712. # self.server_key_dict will yield this key for any of the algorithm
  713. # names.
  714. if isinstance(key, RSAKey):
  715. self.server_key_dict["rsa-sha2-256"] = key
  716. self.server_key_dict["rsa-sha2-512"] = key
  717. def get_server_key(self):
  718. """
  719. Return the active host key, in server mode. After negotiating with the
  720. client, this method will return the negotiated host key. If only one
  721. type of host key was set with `add_server_key`, that's the only key
  722. that will ever be returned. But in cases where you have set more than
  723. one type of host key (for example, an RSA key and a DSS key), the key
  724. type will be negotiated by the client, and this method will return the
  725. key of the type agreed on. If the host key has not been negotiated
  726. yet, ``None`` is returned. In client mode, the behavior is undefined.
  727. :return:
  728. host key (`.PKey`) of the type negotiated by the client, or
  729. ``None``.
  730. """
  731. try:
  732. return self.server_key_dict[self.host_key_type]
  733. except KeyError:
  734. pass
  735. return None
  736. @staticmethod
  737. def load_server_moduli(filename=None):
  738. """
  739. (optional)
  740. Load a file of prime moduli for use in doing group-exchange key
  741. negotiation in server mode. It's a rather obscure option and can be
  742. safely ignored.
  743. In server mode, the remote client may request "group-exchange" key
  744. negotiation, which asks the server to send a random prime number that
  745. fits certain criteria. These primes are pretty difficult to compute,
  746. so they can't be generated on demand. But many systems contain a file
  747. of suitable primes (usually named something like ``/etc/ssh/moduli``).
  748. If you call `load_server_moduli` and it returns ``True``, then this
  749. file of primes has been loaded and we will support "group-exchange" in
  750. server mode. Otherwise server mode will just claim that it doesn't
  751. support that method of key negotiation.
  752. :param str filename:
  753. optional path to the moduli file, if you happen to know that it's
  754. not in a standard location.
  755. :return:
  756. True if a moduli file was successfully loaded; False otherwise.
  757. .. note:: This has no effect when used in client mode.
  758. """
  759. Transport._modulus_pack = ModulusPack()
  760. # places to look for the openssh "moduli" file
  761. file_list = ["/etc/ssh/moduli", "/usr/local/etc/moduli"]
  762. if filename is not None:
  763. file_list.insert(0, filename)
  764. for fn in file_list:
  765. try:
  766. Transport._modulus_pack.read_file(fn)
  767. return True
  768. except IOError:
  769. pass
  770. # none succeeded
  771. Transport._modulus_pack = None
  772. return False
  773. def close(self):
  774. """
  775. Close this session, and any open channels that are tied to it.
  776. """
  777. if not self.active:
  778. return
  779. self.stop_thread()
  780. for chan in list(self._channels.values()):
  781. chan._unlink()
  782. self.sock.close()
  783. def get_remote_server_key(self):
  784. """
  785. Return the host key of the server (in client mode).
  786. .. note::
  787. Previously this call returned a tuple of ``(key type, key
  788. string)``. You can get the same effect by calling `.PKey.get_name`
  789. for the key type, and ``str(key)`` for the key string.
  790. :raises: `.SSHException` -- if no session is currently active.
  791. :return: public key (`.PKey`) of the remote server
  792. """
  793. if (not self.active) or (not self.initial_kex_done):
  794. raise SSHException("No existing session")
  795. return self.host_key
  796. def is_active(self):
  797. """
  798. Return true if this session is active (open).
  799. :return:
  800. True if the session is still active (open); False if the session is
  801. closed
  802. """
  803. return self.active
  804. def open_session(
  805. self, window_size=None, max_packet_size=None, timeout=None
  806. ):
  807. """
  808. Request a new channel to the server, of type ``"session"``. This is
  809. just an alias for calling `open_channel` with an argument of
  810. ``"session"``.
  811. .. note:: Modifying the the window and packet sizes might have adverse
  812. effects on the session created. The default values are the same
  813. as in the OpenSSH code base and have been battle tested.
  814. :param int window_size:
  815. optional window size for this session.
  816. :param int max_packet_size:
  817. optional max packet size for this session.
  818. :return: a new `.Channel`
  819. :raises:
  820. `.SSHException` -- if the request is rejected or the session ends
  821. prematurely
  822. .. versionchanged:: 1.13.4/1.14.3/1.15.3
  823. Added the ``timeout`` argument.
  824. .. versionchanged:: 1.15
  825. Added the ``window_size`` and ``max_packet_size`` arguments.
  826. """
  827. return self.open_channel(
  828. "session",
  829. window_size=window_size,
  830. max_packet_size=max_packet_size,
  831. timeout=timeout,
  832. )
  833. def open_x11_channel(self, src_addr=None):
  834. """
  835. Request a new channel to the client, of type ``"x11"``. This
  836. is just an alias for ``open_channel('x11', src_addr=src_addr)``.
  837. :param tuple src_addr:
  838. the source address (``(str, int)``) of the x11 server (port is the
  839. x11 port, ie. 6010)
  840. :return: a new `.Channel`
  841. :raises:
  842. `.SSHException` -- if the request is rejected or the session ends
  843. prematurely
  844. """
  845. return self.open_channel("x11", src_addr=src_addr)
  846. def open_forward_agent_channel(self):
  847. """
  848. Request a new channel to the client, of type
  849. ``"auth-agent@openssh.com"``.
  850. This is just an alias for ``open_channel('auth-agent@openssh.com')``.
  851. :return: a new `.Channel`
  852. :raises: `.SSHException` --
  853. if the request is rejected or the session ends prematurely
  854. """
  855. return self.open_channel("auth-agent@openssh.com")
  856. def open_forwarded_tcpip_channel(self, src_addr, dest_addr):
  857. """
  858. Request a new channel back to the client, of type ``forwarded-tcpip``.
  859. This is used after a client has requested port forwarding, for sending
  860. incoming connections back to the client.
  861. :param src_addr: originator's address
  862. :param dest_addr: local (server) connected address
  863. """
  864. return self.open_channel("forwarded-tcpip", dest_addr, src_addr)
  865. def open_channel(
  866. self,
  867. kind,
  868. dest_addr=None,
  869. src_addr=None,
  870. window_size=None,
  871. max_packet_size=None,
  872. timeout=None,
  873. ):
  874. """
  875. Request a new channel to the server. `Channels <.Channel>` are
  876. socket-like objects used for the actual transfer of data across the
  877. session. You may only request a channel after negotiating encryption
  878. (using `connect` or `start_client`) and authenticating.
  879. .. note:: Modifying the the window and packet sizes might have adverse
  880. effects on the channel created. The default values are the same
  881. as in the OpenSSH code base and have been battle tested.
  882. :param str kind:
  883. the kind of channel requested (usually ``"session"``,
  884. ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``)
  885. :param tuple dest_addr:
  886. the destination address (address + port tuple) of this port
  887. forwarding, if ``kind`` is ``"forwarded-tcpip"`` or
  888. ``"direct-tcpip"`` (ignored for other channel types)
  889. :param src_addr: the source address of this port forwarding, if
  890. ``kind`` is ``"forwarded-tcpip"``, ``"direct-tcpip"``, or ``"x11"``
  891. :param int window_size:
  892. optional window size for this session.
  893. :param int max_packet_size:
  894. optional max packet size for this session.
  895. :param float timeout:
  896. optional timeout opening a channel, default 3600s (1h)
  897. :return: a new `.Channel` on success
  898. :raises:
  899. `.SSHException` -- if the request is rejected, the session ends
  900. prematurely or there is a timeout openning a channel
  901. .. versionchanged:: 1.15
  902. Added the ``window_size`` and ``max_packet_size`` arguments.
  903. """
  904. if not self.active:
  905. raise SSHException("SSH session not active")
  906. timeout = 3600 if timeout is None else timeout
  907. self.lock.acquire()
  908. try:
  909. window_size = self._sanitize_window_size(window_size)
  910. max_packet_size = self._sanitize_packet_size(max_packet_size)
  911. chanid = self._next_channel()
  912. m = Message()
  913. m.add_byte(cMSG_CHANNEL_OPEN)
  914. m.add_string(kind)
  915. m.add_int(chanid)
  916. m.add_int(window_size)
  917. m.add_int(max_packet_size)
  918. if (kind == "forwarded-tcpip") or (kind == "direct-tcpip"):
  919. m.add_string(dest_addr[0])
  920. m.add_int(dest_addr[1])
  921. m.add_string(src_addr[0])
  922. m.add_int(src_addr[1])
  923. elif kind == "x11":
  924. m.add_string(src_addr[0])
  925. m.add_int(src_addr[1])
  926. chan = Channel(chanid)
  927. self._channels.put(chanid, chan)
  928. self.channel_events[chanid] = event = threading.Event()
  929. self.channels_seen[chanid] = True
  930. chan._set_transport(self)
  931. chan._set_window(window_size, max_packet_size)
  932. finally:
  933. self.lock.release()
  934. self._send_user_message(m)
  935. start_ts = time.time()
  936. while True:
  937. event.wait(0.1)
  938. if not self.active:
  939. e = self.get_exception()
  940. if e is None:
  941. e = SSHException("Unable to open channel.")
  942. raise e
  943. if event.is_set():
  944. break
  945. elif start_ts + timeout < time.time():
  946. raise SSHException("Timeout opening channel.")
  947. chan = self._channels.get(chanid)
  948. if chan is not None:
  949. return chan
  950. e = self.get_exception()
  951. if e is None:
  952. e = SSHException("Unable to open channel.")
  953. raise e
  954. def request_port_forward(self, address, port, handler=None):
  955. """
  956. Ask the server to forward TCP connections from a listening port on
  957. the server, across this SSH session.
  958. If a handler is given, that handler is called from a different thread
  959. whenever a forwarded connection arrives. The handler parameters are::
  960. handler(
  961. channel,
  962. (origin_addr, origin_port),
  963. (server_addr, server_port),
  964. )
  965. where ``server_addr`` and ``server_port`` are the address and port that
  966. the server was listening on.
  967. If no handler is set, the default behavior is to send new incoming
  968. forwarded connections into the accept queue, to be picked up via
  969. `accept`.
  970. :param str address: the address to bind when forwarding
  971. :param int port:
  972. the port to forward, or 0 to ask the server to allocate any port
  973. :param callable handler:
  974. optional handler for incoming forwarded connections, of the form
  975. ``func(Channel, (str, int), (str, int))``.
  976. :return: the port number (`int`) allocated by the server
  977. :raises:
  978. `.SSHException` -- if the server refused the TCP forward request
  979. """
  980. if not self.active:
  981. raise SSHException("SSH session not active")
  982. port = int(port)
  983. response = self.global_request(
  984. "tcpip-forward", (address, port), wait=True
  985. )
  986. if response is None:
  987. raise SSHException("TCP forwarding request denied")
  988. if port == 0:
  989. port = response.get_int()
  990. if handler is None:
  991. def default_handler(channel, src_addr, dest_addr_port):
  992. # src_addr, src_port = src_addr_port
  993. # dest_addr, dest_port = dest_addr_port
  994. self._queue_incoming_channel(channel)
  995. handler = default_handler
  996. self._tcp_handler = handler
  997. return port
  998. def cancel_port_forward(self, address, port):
  999. """
  1000. Ask the server to cancel a previous port-forwarding request. No more
  1001. connections to the given address & port will be forwarded across this
  1002. ssh connection.
  1003. :param str address: the address to stop forwarding
  1004. :param int port: the port to stop forwarding
  1005. """
  1006. if not self.active:
  1007. return
  1008. self._tcp_handler = None
  1009. self.global_request("cancel-tcpip-forward", (address, port), wait=True)
  1010. def open_sftp_client(self):
  1011. """
  1012. Create an SFTP client channel from an open transport. On success, an
  1013. SFTP session will be opened with the remote host, and a new
  1014. `.SFTPClient` object will be returned.
  1015. :return:
  1016. a new `.SFTPClient` referring to an sftp session (channel) across
  1017. this transport
  1018. """
  1019. return SFTPClient.from_transport(self)
  1020. def send_ignore(self, byte_count=None):
  1021. """
  1022. Send a junk packet across the encrypted link. This is sometimes used
  1023. to add "noise" to a connection to confuse would-be attackers. It can
  1024. also be used as a keep-alive for long lived connections traversing
  1025. firewalls.
  1026. :param int byte_count:
  1027. the number of random bytes to send in the payload of the ignored
  1028. packet -- defaults to a random number from 10 to 41.
  1029. """
  1030. m = Message()
  1031. m.add_byte(cMSG_IGNORE)
  1032. if byte_count is None:
  1033. byte_count = (byte_ord(os.urandom(1)) % 32) + 10
  1034. m.add_bytes(os.urandom(byte_count))
  1035. self._send_user_message(m)
  1036. def renegotiate_keys(self):
  1037. """
  1038. Force this session to switch to new keys. Normally this is done
  1039. automatically after the session hits a certain number of packets or
  1040. bytes sent or received, but this method gives you the option of forcing
  1041. new keys whenever you want. Negotiating new keys causes a pause in
  1042. traffic both ways as the two sides swap keys and do computations. This
  1043. method returns when the session has switched to new keys.
  1044. :raises:
  1045. `.SSHException` -- if the key renegotiation failed (which causes
  1046. the session to end)
  1047. """
  1048. self.completion_event = threading.Event()
  1049. self._send_kex_init()
  1050. while True:
  1051. self.completion_event.wait(0.1)
  1052. if not self.active:
  1053. e = self.get_exception()
  1054. if e is not None:
  1055. raise e
  1056. raise SSHException("Negotiation failed.")
  1057. if self.completion_event.is_set():
  1058. break
  1059. return
  1060. def set_keepalive(self, interval):
  1061. """
  1062. Turn on/off keepalive packets (default is off). If this is set, after
  1063. ``interval`` seconds without sending any data over the connection, a
  1064. "keepalive" packet will be sent (and ignored by the remote host). This
  1065. can be useful to keep connections alive over a NAT, for example.
  1066. :param int interval:
  1067. seconds to wait before sending a keepalive packet (or
  1068. 0 to disable keepalives).
  1069. """
  1070. def _request(x=weakref.proxy(self)):
  1071. return x.global_request("keepalive@lag.net", wait=False)
  1072. self.packetizer.set_keepalive(interval, _request)
  1073. def global_request(self, kind, data=None, wait=True):
  1074. """
  1075. Make a global request to the remote host. These are normally
  1076. extensions to the SSH2 protocol.
  1077. :param str kind: name of the request.
  1078. :param tuple data:
  1079. an optional tuple containing additional data to attach to the
  1080. request.
  1081. :param bool wait:
  1082. ``True`` if this method should not return until a response is
  1083. received; ``False`` otherwise.
  1084. :return:
  1085. a `.Message` containing possible additional data if the request was
  1086. successful (or an empty `.Message` if ``wait`` was ``False``);
  1087. ``None`` if the request was denied.
  1088. """
  1089. if wait:
  1090. self.completion_event = threading.Event()
  1091. m = Message()
  1092. m.add_byte(cMSG_GLOBAL_REQUEST)
  1093. m.add_string(kind)
  1094. m.add_boolean(wait)
  1095. if data is not None:
  1096. m.add(*data)
  1097. self._log(DEBUG, 'Sending global request "{}"'.format(kind))
  1098. self._send_user_message(m)
  1099. if not wait:
  1100. return None
  1101. while True:
  1102. self.completion_event.wait(0.1)
  1103. if not self.active:
  1104. return None
  1105. if self.completion_event.is_set():
  1106. break
  1107. return self.global_response
  1108. def accept(self, timeout=None):
  1109. """
  1110. Return the next channel opened by the client over this transport, in
  1111. server mode. If no channel is opened before the given timeout,
  1112. ``None`` is returned.
  1113. :param int timeout:
  1114. seconds to wait for a channel, or ``None`` to wait forever
  1115. :return: a new `.Channel` opened by the client
  1116. """
  1117. self.lock.acquire()
  1118. try:
  1119. if len(self.server_accepts) > 0:
  1120. chan = self.server_accepts.pop(0)
  1121. else:
  1122. self.server_accept_cv.wait(timeout)
  1123. if len(self.server_accepts) > 0:
  1124. chan = self.server_accepts.pop(0)
  1125. else:
  1126. # timeout
  1127. chan = None
  1128. finally:
  1129. self.lock.release()
  1130. return chan
  1131. def connect(
  1132. self,
  1133. hostkey=None,
  1134. username="",
  1135. password=None,
  1136. pkey=None,
  1137. gss_host=None,
  1138. gss_auth=False,
  1139. gss_kex=False,
  1140. gss_deleg_creds=True,
  1141. gss_trust_dns=True,
  1142. ):
  1143. """
  1144. Negotiate an SSH2 session, and optionally verify the server's host key
  1145. and authenticate using a password or private key. This is a shortcut
  1146. for `start_client`, `get_remote_server_key`, and
  1147. `Transport.auth_password` or `Transport.auth_publickey`. Use those
  1148. methods if you want more control.
  1149. You can use this method immediately after creating a Transport to
  1150. negotiate encryption with a server. If it fails, an exception will be
  1151. thrown. On success, the method will return cleanly, and an encrypted
  1152. session exists. You may immediately call `open_channel` or
  1153. `open_session` to get a `.Channel` object, which is used for data
  1154. transfer.
  1155. .. note::
  1156. If you fail to supply a password or private key, this method may
  1157. succeed, but a subsequent `open_channel` or `open_session` call may
  1158. fail because you haven't authenticated yet.
  1159. :param .PKey hostkey:
  1160. the host key expected from the server, or ``None`` if you don't
  1161. want to do host key verification.
  1162. :param str username: the username to authenticate as.
  1163. :param str password:
  1164. a password to use for authentication, if you want to use password
  1165. authentication; otherwise ``None``.
  1166. :param .PKey pkey:
  1167. a private key to use for authentication, if you want to use private
  1168. key authentication; otherwise ``None``.
  1169. :param str gss_host:
  1170. The target's name in the kerberos database. Default: hostname
  1171. :param bool gss_auth:
  1172. ``True`` if you want to use GSS-API authentication.
  1173. :param bool gss_kex:
  1174. Perform GSS-API Key Exchange and user authentication.
  1175. :param bool gss_deleg_creds:
  1176. Whether to delegate GSS-API client credentials.
  1177. :param gss_trust_dns:
  1178. Indicates whether or not the DNS is trusted to securely
  1179. canonicalize the name of the host being connected to (default
  1180. ``True``).
  1181. :raises: `.SSHException` -- if the SSH2 negotiation fails, the host key
  1182. supplied by the server is incorrect, or authentication fails.
  1183. .. versionchanged:: 2.3
  1184. Added the ``gss_trust_dns`` argument.
  1185. """
  1186. if hostkey is not None:
  1187. # TODO: a more robust implementation would be to ask each key class
  1188. # for its nameS plural, and just use that.
  1189. # TODO: that could be used in a bunch of other spots too
  1190. if isinstance(hostkey, RSAKey):
  1191. self._preferred_keys = [
  1192. "rsa-sha2-512",
  1193. "rsa-sha2-256",
  1194. "ssh-rsa",
  1195. ]
  1196. else:
  1197. self._preferred_keys = [hostkey.get_name()]
  1198. self.set_gss_host(
  1199. gss_host=gss_host,
  1200. trust_dns=gss_trust_dns,
  1201. gssapi_requested=gss_kex or gss_auth,
  1202. )
  1203. self.start_client()
  1204. # check host key if we were given one
  1205. # If GSS-API Key Exchange was performed, we are not required to check
  1206. # the host key.
  1207. if (hostkey is not None) and not gss_kex:
  1208. key = self.get_remote_server_key()
  1209. if (
  1210. key.get_name() != hostkey.get_name()
  1211. or key.asbytes() != hostkey.asbytes()
  1212. ):
  1213. self._log(DEBUG, "Bad host key from server")
  1214. self._log(
  1215. DEBUG,
  1216. "Expected: {}: {}".format(
  1217. hostkey.get_name(), repr(hostkey.asbytes())
  1218. ),
  1219. )
  1220. self._log(
  1221. DEBUG,
  1222. "Got : {}: {}".format(
  1223. key.get_name(), repr(key.asbytes())
  1224. ),
  1225. )
  1226. raise SSHException("Bad host key from server")
  1227. self._log(
  1228. DEBUG, "Host key verified ({})".format(hostkey.get_name())
  1229. )
  1230. if (pkey is not None) or (password is not None) or gss_auth or gss_kex:
  1231. if gss_auth:
  1232. self._log(
  1233. DEBUG, "Attempting GSS-API auth... (gssapi-with-mic)"
  1234. ) # noqa
  1235. self.auth_gssapi_with_mic(
  1236. username, self.gss_host, gss_deleg_creds
  1237. )
  1238. elif gss_kex:
  1239. self._log(DEBUG, "Attempting GSS-API auth... (gssapi-keyex)")
  1240. self.auth_gssapi_keyex(username)
  1241. elif pkey is not None:
  1242. self._log(DEBUG, "Attempting public-key auth...")
  1243. self.auth_publickey(username, pkey)
  1244. else:
  1245. self._log(DEBUG, "Attempting password auth...")
  1246. self.auth_password(username, password)
  1247. return
  1248. def get_exception(self):
  1249. """
  1250. Return any exception that happened during the last server request.
  1251. This can be used to fetch more specific error information after using
  1252. calls like `start_client`. The exception (if any) is cleared after
  1253. this call.
  1254. :return:
  1255. an exception, or ``None`` if there is no stored exception.
  1256. .. versionadded:: 1.1
  1257. """
  1258. self.lock.acquire()
  1259. try:
  1260. e = self.saved_exception
  1261. self.saved_exception = None
  1262. return e
  1263. finally:
  1264. self.lock.release()
  1265. def set_subsystem_handler(self, name, handler, *larg, **kwarg):
  1266. """
  1267. Set the handler class for a subsystem in server mode. If a request
  1268. for this subsystem is made on an open ssh channel later, this handler
  1269. will be constructed and called -- see `.SubsystemHandler` for more
  1270. detailed documentation.
  1271. Any extra parameters (including keyword arguments) are saved and
  1272. passed to the `.SubsystemHandler` constructor later.
  1273. :param str name: name of the subsystem.
  1274. :param handler:
  1275. subclass of `.SubsystemHandler` that handles this subsystem.
  1276. """
  1277. try:
  1278. self.lock.acquire()
  1279. self.subsystem_table[name] = (handler, larg, kwarg)
  1280. finally:
  1281. self.lock.release()
  1282. def is_authenticated(self):
  1283. """
  1284. Return true if this session is active and authenticated.
  1285. :return:
  1286. True if the session is still open and has been authenticated
  1287. successfully; False if authentication failed and/or the session is
  1288. closed.
  1289. """
  1290. return (
  1291. self.active
  1292. and self.auth_handler is not None
  1293. and self.auth_handler.is_authenticated()
  1294. )
  1295. def get_username(self):
  1296. """
  1297. Return the username this connection is authenticated for. If the
  1298. session is not authenticated (or authentication failed), this method
  1299. returns ``None``.
  1300. :return: username that was authenticated (a `str`), or ``None``.
  1301. """
  1302. if not self.active or (self.auth_handler is None):
  1303. return None
  1304. return self.auth_handler.get_username()
  1305. def get_banner(self):
  1306. """
  1307. Return the banner supplied by the server upon connect. If no banner is
  1308. supplied, this method returns ``None``.
  1309. :returns: server supplied banner (`str`), or ``None``.
  1310. .. versionadded:: 1.13
  1311. """
  1312. if not self.active or (self.auth_handler is None):
  1313. return None
  1314. return self.auth_handler.banner
  1315. def auth_none(self, username):
  1316. """
  1317. Try to authenticate to the server using no authentication at all.
  1318. This will almost always fail. It may be useful for determining the
  1319. list of authentication types supported by the server, by catching the
  1320. `.BadAuthenticationType` exception raised.
  1321. :param str username: the username to authenticate as
  1322. :return:
  1323. list of auth types permissible for the next stage of
  1324. authentication (normally empty)
  1325. :raises:
  1326. `.BadAuthenticationType` -- if "none" authentication isn't allowed
  1327. by the server for this user
  1328. :raises:
  1329. `.SSHException` -- if the authentication failed due to a network
  1330. error
  1331. .. versionadded:: 1.5
  1332. """
  1333. if (not self.active) or (not self.initial_kex_done):
  1334. raise SSHException("No existing session")
  1335. my_event = threading.Event()
  1336. self.auth_handler = AuthHandler(self)
  1337. self.auth_handler.auth_none(username, my_event)
  1338. return self.auth_handler.wait_for_response(my_event)
  1339. def auth_password(self, username, password, event=None, fallback=True):
  1340. """
  1341. Authenticate to the server using a password. The username and password
  1342. are sent over an encrypted link.
  1343. If an ``event`` is passed in, this method will return immediately, and
  1344. the event will be triggered once authentication succeeds or fails. On
  1345. success, `is_authenticated` will return ``True``. On failure, you may
  1346. use `get_exception` to get more detailed error information.
  1347. Since 1.1, if no event is passed, this method will block until the
  1348. authentication succeeds or fails. On failure, an exception is raised.
  1349. Otherwise, the method simply returns.
  1350. Since 1.5, if no event is passed and ``fallback`` is ``True`` (the
  1351. default), if the server doesn't support plain password authentication
  1352. but does support so-called "keyboard-interactive" mode, an attempt
  1353. will be made to authenticate using this interactive mode. If it fails,
  1354. the normal exception will be thrown as if the attempt had never been
  1355. made. This is useful for some recent Gentoo and Debian distributions,
  1356. which turn off plain password authentication in a misguided belief
  1357. that interactive authentication is "more secure". (It's not.)
  1358. If the server requires multi-step authentication (which is very rare),
  1359. this method will return a list of auth types permissible for the next
  1360. step. Otherwise, in the normal case, an empty list is returned.
  1361. :param str username: the username to authenticate as
  1362. :param basestring password: the password to authenticate with
  1363. :param .threading.Event event:
  1364. an event to trigger when the authentication attempt is complete
  1365. (whether it was successful or not)
  1366. :param bool fallback:
  1367. ``True`` if an attempt at an automated "interactive" password auth
  1368. should be made if the server doesn't support normal password auth
  1369. :return:
  1370. list of auth types permissible for the next stage of
  1371. authentication (normally empty)
  1372. :raises:
  1373. `.BadAuthenticationType` -- if password authentication isn't
  1374. allowed by the server for this user (and no event was passed in)
  1375. :raises:
  1376. `.AuthenticationException` -- if the authentication failed (and no
  1377. event was passed in)
  1378. :raises: `.SSHException` -- if there was a network error
  1379. """
  1380. if (not self.active) or (not self.initial_kex_done):
  1381. # we should never try to send the password unless we're on a secure
  1382. # link
  1383. raise SSHException("No existing session")
  1384. if event is None:
  1385. my_event = threading.Event()
  1386. else:
  1387. my_event = event
  1388. self.auth_handler = AuthHandler(self)
  1389. self.auth_handler.auth_password(username, password, my_event)
  1390. if event is not None:
  1391. # caller wants to wait for event themselves
  1392. return []
  1393. try:
  1394. return self.auth_handler.wait_for_response(my_event)
  1395. except BadAuthenticationType as e:
  1396. # if password auth isn't allowed, but keyboard-interactive *is*,
  1397. # try to fudge it
  1398. if not fallback or ("keyboard-interactive" not in e.allowed_types):
  1399. raise
  1400. try:
  1401. def handler(title, instructions, fields):
  1402. if len(fields) > 1:
  1403. raise SSHException("Fallback authentication failed.")
  1404. if len(fields) == 0:
  1405. # for some reason, at least on os x, a 2nd request will
  1406. # be made with zero fields requested. maybe it's just
  1407. # to try to fake out automated scripting of the exact
  1408. # type we're doing here. *shrug* :)
  1409. return []
  1410. return [password]
  1411. return self.auth_interactive(username, handler)
  1412. except SSHException:
  1413. # attempt failed; just raise the original exception
  1414. raise e
  1415. def auth_publickey(self, username, key, event=None):
  1416. """
  1417. Authenticate to the server using a private key. The key is used to
  1418. sign data from the server, so it must include the private part.
  1419. If an ``event`` is passed in, this method will return immediately, and
  1420. the event will be triggered once authentication succeeds or fails. On
  1421. success, `is_authenticated` will return ``True``. On failure, you may
  1422. use `get_exception` to get more detailed error information.
  1423. Since 1.1, if no event is passed, this method will block until the
  1424. authentication succeeds or fails. On failure, an exception is raised.
  1425. Otherwise, the method simply returns.
  1426. If the server requires multi-step authentication (which is very rare),
  1427. this method will return a list of auth types permissible for the next
  1428. step. Otherwise, in the normal case, an empty list is returned.
  1429. :param str username: the username to authenticate as
  1430. :param .PKey key: the private key to authenticate with
  1431. :param .threading.Event event:
  1432. an event to trigger when the authentication attempt is complete
  1433. (whether it was successful or not)
  1434. :return:
  1435. list of auth types permissible for the next stage of
  1436. authentication (normally empty)
  1437. :raises:
  1438. `.BadAuthenticationType` -- if public-key authentication isn't
  1439. allowed by the server for this user (and no event was passed in)
  1440. :raises:
  1441. `.AuthenticationException` -- if the authentication failed (and no
  1442. event was passed in)
  1443. :raises: `.SSHException` -- if there was a network error
  1444. """
  1445. if (not self.active) or (not self.initial_kex_done):
  1446. # we should never try to authenticate unless we're on a secure link
  1447. raise SSHException("No existing session")
  1448. if event is None:
  1449. my_event = threading.Event()
  1450. else:
  1451. my_event = event
  1452. self.auth_handler = AuthHandler(self)
  1453. self.auth_handler.auth_publickey(username, key, my_event)
  1454. if event is not None:
  1455. # caller wants to wait for event themselves
  1456. return []
  1457. return self.auth_handler.wait_for_response(my_event)
  1458. def auth_interactive(self, username, handler, submethods=""):
  1459. """
  1460. Authenticate to the server interactively. A handler is used to answer
  1461. arbitrary questions from the server. On many servers, this is just a
  1462. dumb wrapper around PAM.
  1463. This method will block until the authentication succeeds or fails,
  1464. peroidically calling the handler asynchronously to get answers to
  1465. authentication questions. The handler may be called more than once
  1466. if the server continues to ask questions.
  1467. The handler is expected to be a callable that will handle calls of the
  1468. form: ``handler(title, instructions, prompt_list)``. The ``title`` is
  1469. meant to be a dialog-window title, and the ``instructions`` are user
  1470. instructions (both are strings). ``prompt_list`` will be a list of
  1471. prompts, each prompt being a tuple of ``(str, bool)``. The string is
  1472. the prompt and the boolean indicates whether the user text should be
  1473. echoed.
  1474. A sample call would thus be:
  1475. ``handler('title', 'instructions', [('Password:', False)])``.
  1476. The handler should return a list or tuple of answers to the server's
  1477. questions.
  1478. If the server requires multi-step authentication (which is very rare),
  1479. this method will return a list of auth types permissible for the next
  1480. step. Otherwise, in the normal case, an empty list is returned.
  1481. :param str username: the username to authenticate as
  1482. :param callable handler: a handler for responding to server questions
  1483. :param str submethods: a string list of desired submethods (optional)
  1484. :return:
  1485. list of auth types permissible for the next stage of
  1486. authentication (normally empty).
  1487. :raises: `.BadAuthenticationType` -- if public-key authentication isn't
  1488. allowed by the server for this user
  1489. :raises: `.AuthenticationException` -- if the authentication failed
  1490. :raises: `.SSHException` -- if there was a network error
  1491. .. versionadded:: 1.5
  1492. """
  1493. if (not self.active) or (not self.initial_kex_done):
  1494. # we should never try to authenticate unless we're on a secure link
  1495. raise SSHException("No existing session")
  1496. my_event = threading.Event()
  1497. self.auth_handler = AuthHandler(self)
  1498. self.auth_handler.auth_interactive(
  1499. username, handler, my_event, submethods
  1500. )
  1501. return self.auth_handler.wait_for_response(my_event)
  1502. def auth_interactive_dumb(self, username, handler=None, submethods=""):
  1503. """
  1504. Autenticate to the server interactively but dumber.
  1505. Just print the prompt and / or instructions to stdout and send back
  1506. the response. This is good for situations where partial auth is
  1507. achieved by key and then the user has to enter a 2fac token.
  1508. """
  1509. if not handler:
  1510. def handler(title, instructions, prompt_list):
  1511. answers = []
  1512. if title:
  1513. print(title.strip())
  1514. if instructions:
  1515. print(instructions.strip())
  1516. for prompt, show_input in prompt_list:
  1517. print(prompt.strip(), end=" ")
  1518. answers.append(input())
  1519. return answers
  1520. return self.auth_interactive(username, handler, submethods)
  1521. def auth_gssapi_with_mic(self, username, gss_host, gss_deleg_creds):
  1522. """
  1523. Authenticate to the Server using GSS-API / SSPI.
  1524. :param str username: The username to authenticate as
  1525. :param str gss_host: The target host
  1526. :param bool gss_deleg_creds: Delegate credentials or not
  1527. :return: list of auth types permissible for the next stage of
  1528. authentication (normally empty)
  1529. :raises: `.BadAuthenticationType` -- if gssapi-with-mic isn't
  1530. allowed by the server (and no event was passed in)
  1531. :raises:
  1532. `.AuthenticationException` -- if the authentication failed (and no
  1533. event was passed in)
  1534. :raises: `.SSHException` -- if there was a network error
  1535. """
  1536. if (not self.active) or (not self.initial_kex_done):
  1537. # we should never try to authenticate unless we're on a secure link
  1538. raise SSHException("No existing session")
  1539. my_event = threading.Event()
  1540. self.auth_handler = AuthHandler(self)
  1541. self.auth_handler.auth_gssapi_with_mic(
  1542. username, gss_host, gss_deleg_creds, my_event
  1543. )
  1544. return self.auth_handler.wait_for_response(my_event)
  1545. def auth_gssapi_keyex(self, username):
  1546. """
  1547. Authenticate to the server with GSS-API/SSPI if GSS-API kex is in use.
  1548. :param str username: The username to authenticate as.
  1549. :returns:
  1550. a list of auth types permissible for the next stage of
  1551. authentication (normally empty)
  1552. :raises: `.BadAuthenticationType` --
  1553. if GSS-API Key Exchange was not performed (and no event was passed
  1554. in)
  1555. :raises: `.AuthenticationException` --
  1556. if the authentication failed (and no event was passed in)
  1557. :raises: `.SSHException` -- if there was a network error
  1558. """
  1559. if (not self.active) or (not self.initial_kex_done):
  1560. # we should never try to authenticate unless we're on a secure link
  1561. raise SSHException("No existing session")
  1562. my_event = threading.Event()
  1563. self.auth_handler = AuthHandler(self)
  1564. self.auth_handler.auth_gssapi_keyex(username, my_event)
  1565. return self.auth_handler.wait_for_response(my_event)
  1566. def set_log_channel(self, name):
  1567. """
  1568. Set the channel for this transport's logging. The default is
  1569. ``"paramiko.transport"`` but it can be set to anything you want. (See
  1570. the `.logging` module for more info.) SSH Channels will log to a
  1571. sub-channel of the one specified.
  1572. :param str name: new channel name for logging
  1573. .. versionadded:: 1.1
  1574. """
  1575. self.log_name = name
  1576. self.logger = util.get_logger(name)
  1577. self.packetizer.set_log(self.logger)
  1578. def get_log_channel(self):
  1579. """
  1580. Return the channel name used for this transport's logging.
  1581. :return: channel name as a `str`
  1582. .. versionadded:: 1.2
  1583. """
  1584. return self.log_name
  1585. def set_hexdump(self, hexdump):
  1586. """
  1587. Turn on/off logging a hex dump of protocol traffic at DEBUG level in
  1588. the logs. Normally you would want this off (which is the default),
  1589. but if you are debugging something, it may be useful.
  1590. :param bool hexdump:
  1591. ``True`` to log protocol traffix (in hex) to the log; ``False``
  1592. otherwise.
  1593. """
  1594. self.packetizer.set_hexdump(hexdump)
  1595. def get_hexdump(self):
  1596. """
  1597. Return ``True`` if the transport is currently logging hex dumps of
  1598. protocol traffic.
  1599. :return: ``True`` if hex dumps are being logged, else ``False``.
  1600. .. versionadded:: 1.4
  1601. """
  1602. return self.packetizer.get_hexdump()
  1603. def use_compression(self, compress=True):
  1604. """
  1605. Turn on/off compression. This will only have an affect before starting
  1606. the transport (ie before calling `connect`, etc). By default,
  1607. compression is off since it negatively affects interactive sessions.
  1608. :param bool compress:
  1609. ``True`` to ask the remote client/server to compress traffic;
  1610. ``False`` to refuse compression
  1611. .. versionadded:: 1.5.2
  1612. """
  1613. if compress:
  1614. self._preferred_compression = ("zlib@openssh.com", "zlib", "none")
  1615. else:
  1616. self._preferred_compression = ("none",)
  1617. def getpeername(self):
  1618. """
  1619. Return the address of the remote side of this Transport, if possible.
  1620. This is effectively a wrapper around ``getpeername`` on the underlying
  1621. socket. If the socket-like object has no ``getpeername`` method, then
  1622. ``("unknown", 0)`` is returned.
  1623. :return:
  1624. the address of the remote host, if known, as a ``(str, int)``
  1625. tuple.
  1626. """
  1627. gp = getattr(self.sock, "getpeername", None)
  1628. if gp is None:
  1629. return "unknown", 0
  1630. return gp()
  1631. def stop_thread(self):
  1632. self.active = False
  1633. self.packetizer.close()
  1634. if PY2:
  1635. # Original join logic; #520 doesn't appear commonly present under
  1636. # Python 2.
  1637. while self.is_alive() and self is not threading.current_thread():
  1638. self.join(10)
  1639. else:
  1640. # Keep trying to join() our main thread, quickly, until:
  1641. # * We join()ed successfully (self.is_alive() == False)
  1642. # * Or it looks like we've hit issue #520 (socket.recv hitting some
  1643. # race condition preventing it from timing out correctly), wherein
  1644. # our socket and packetizer are both closed (but where we'd
  1645. # otherwise be sitting forever on that recv()).
  1646. while (
  1647. self.is_alive()
  1648. and self is not threading.current_thread()
  1649. and not self.sock._closed
  1650. and not self.packetizer.closed
  1651. ):
  1652. self.join(0.1)
  1653. # internals...
  1654. def _log(self, level, msg, *args):
  1655. if issubclass(type(msg), list):
  1656. for m in msg:
  1657. self.logger.log(level, m)
  1658. else:
  1659. self.logger.log(level, msg, *args)
  1660. def _get_modulus_pack(self):
  1661. """used by KexGex to find primes for group exchange"""
  1662. return self._modulus_pack
  1663. def _next_channel(self):
  1664. """you are holding the lock"""
  1665. chanid = self._channel_counter
  1666. while self._channels.get(chanid) is not None:
  1667. self._channel_counter = (self._channel_counter + 1) & 0xffffff
  1668. chanid = self._channel_counter
  1669. self._channel_counter = (self._channel_counter + 1) & 0xffffff
  1670. return chanid
  1671. def _unlink_channel(self, chanid):
  1672. """used by a Channel to remove itself from the active channel list"""
  1673. self._channels.delete(chanid)
  1674. def _send_message(self, data):
  1675. self.packetizer.send_message(data)
  1676. def _send_user_message(self, data):
  1677. """
  1678. send a message, but block if we're in key negotiation. this is used
  1679. for user-initiated requests.
  1680. """
  1681. start = time.time()
  1682. while True:
  1683. self.clear_to_send.wait(0.1)
  1684. if not self.active:
  1685. self._log(
  1686. DEBUG, "Dropping user packet because connection is dead."
  1687. ) # noqa
  1688. return
  1689. self.clear_to_send_lock.acquire()
  1690. if self.clear_to_send.is_set():
  1691. break
  1692. self.clear_to_send_lock.release()
  1693. if time.time() > start + self.clear_to_send_timeout:
  1694. raise SSHException(
  1695. "Key-exchange timed out waiting for key negotiation"
  1696. ) # noqa
  1697. try:
  1698. self._send_message(data)
  1699. finally:
  1700. self.clear_to_send_lock.release()
  1701. def _set_K_H(self, k, h):
  1702. """
  1703. Used by a kex obj to set the K (root key) and H (exchange hash).
  1704. """
  1705. self.K = k
  1706. self.H = h
  1707. if self.session_id is None:
  1708. self.session_id = h
  1709. def _expect_packet(self, *ptypes):
  1710. """
  1711. Used by a kex obj to register the next packet type it expects to see.
  1712. """
  1713. self._expected_packet = tuple(ptypes)
  1714. def _verify_key(self, host_key, sig):
  1715. key = self._key_info[self.host_key_type](Message(host_key))
  1716. if key is None:
  1717. raise SSHException("Unknown host key type")
  1718. if not key.verify_ssh_sig(self.H, Message(sig)):
  1719. raise SSHException(
  1720. "Signature verification ({}) failed.".format(
  1721. self.host_key_type
  1722. )
  1723. ) # noqa
  1724. self.host_key = key
  1725. def _compute_key(self, id, nbytes):
  1726. """id is 'A' - 'F' for the various keys used by ssh"""
  1727. m = Message()
  1728. m.add_mpint(self.K)
  1729. m.add_bytes(self.H)
  1730. m.add_byte(b(id))
  1731. m.add_bytes(self.session_id)
  1732. # Fallback to SHA1 for kex engines that fail to specify a hex
  1733. # algorithm, or for e.g. transport tests that don't run kexinit.
  1734. hash_algo = getattr(self.kex_engine, "hash_algo", None)
  1735. hash_select_msg = "kex engine {} specified hash_algo {!r}".format(
  1736. self.kex_engine.__class__.__name__, hash_algo
  1737. )
  1738. if hash_algo is None:
  1739. hash_algo = sha1
  1740. hash_select_msg += ", falling back to sha1"
  1741. if not hasattr(self, "_logged_hash_selection"):
  1742. self._log(DEBUG, hash_select_msg)
  1743. setattr(self, "_logged_hash_selection", True)
  1744. out = sofar = hash_algo(m.asbytes()).digest()
  1745. while len(out) < nbytes:
  1746. m = Message()
  1747. m.add_mpint(self.K)
  1748. m.add_bytes(self.H)
  1749. m.add_bytes(sofar)
  1750. digest = hash_algo(m.asbytes()).digest()
  1751. out += digest
  1752. sofar += digest
  1753. return out[:nbytes]
  1754. def _get_cipher(self, name, key, iv, operation):
  1755. if name not in self._cipher_info:
  1756. raise SSHException("Unknown client cipher " + name)
  1757. else:
  1758. cipher = Cipher(
  1759. self._cipher_info[name]["class"](key),
  1760. self._cipher_info[name]["mode"](iv),
  1761. backend=default_backend(),
  1762. )
  1763. if operation is self._ENCRYPT:
  1764. return cipher.encryptor()
  1765. else:
  1766. return cipher.decryptor()
  1767. def _set_forward_agent_handler(self, handler):
  1768. if handler is None:
  1769. def default_handler(channel):
  1770. self._queue_incoming_channel(channel)
  1771. self._forward_agent_handler = default_handler
  1772. else:
  1773. self._forward_agent_handler = handler
  1774. def _set_x11_handler(self, handler):
  1775. # only called if a channel has turned on x11 forwarding
  1776. if handler is None:
  1777. # by default, use the same mechanism as accept()
  1778. def default_handler(channel, src_addr_port):
  1779. self._queue_incoming_channel(channel)
  1780. self._x11_handler = default_handler
  1781. else:
  1782. self._x11_handler = handler
  1783. def _queue_incoming_channel(self, channel):
  1784. self.lock.acquire()
  1785. try:
  1786. self.server_accepts.append(channel)
  1787. self.server_accept_cv.notify()
  1788. finally:
  1789. self.lock.release()
  1790. def _sanitize_window_size(self, window_size):
  1791. if window_size is None:
  1792. window_size = self.default_window_size
  1793. return clamp_value(MIN_WINDOW_SIZE, window_size, MAX_WINDOW_SIZE)
  1794. def _sanitize_packet_size(self, max_packet_size):
  1795. if max_packet_size is None:
  1796. max_packet_size = self.default_max_packet_size
  1797. return clamp_value(MIN_PACKET_SIZE, max_packet_size, MAX_WINDOW_SIZE)
  1798. def _ensure_authed(self, ptype, message):
  1799. """
  1800. Checks message type against current auth state.
  1801. If server mode, and auth has not succeeded, and the message is of a
  1802. post-auth type (channel open or global request) an appropriate error
  1803. response Message is crafted and returned to caller for sending.
  1804. Otherwise (client mode, authed, or pre-auth message) returns None.
  1805. """
  1806. if (
  1807. not self.server_mode
  1808. or ptype <= HIGHEST_USERAUTH_MESSAGE_ID
  1809. or self.is_authenticated()
  1810. ):
  1811. return None
  1812. # WELP. We must be dealing with someone trying to do non-auth things
  1813. # without being authed. Tell them off, based on message class.
  1814. reply = Message()
  1815. # Global requests have no details, just failure.
  1816. if ptype == MSG_GLOBAL_REQUEST:
  1817. reply.add_byte(cMSG_REQUEST_FAILURE)
  1818. # Channel opens let us reject w/ a specific type + message.
  1819. elif ptype == MSG_CHANNEL_OPEN:
  1820. kind = message.get_text() # noqa
  1821. chanid = message.get_int()
  1822. reply.add_byte(cMSG_CHANNEL_OPEN_FAILURE)
  1823. reply.add_int(chanid)
  1824. reply.add_int(OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED)
  1825. reply.add_string("")
  1826. reply.add_string("en")
  1827. # NOTE: Post-open channel messages do not need checking; the above will
  1828. # reject attemps to open channels, meaning that even if a malicious
  1829. # user tries to send a MSG_CHANNEL_REQUEST, it will simply fall under
  1830. # the logic that handles unknown channel IDs (as the channel list will
  1831. # be empty.)
  1832. return reply
  1833. def run(self):
  1834. # (use the exposed "run" method, because if we specify a thread target
  1835. # of a private method, threading.Thread will keep a reference to it
  1836. # indefinitely, creating a GC cycle and not letting Transport ever be
  1837. # GC'd. it's a bug in Thread.)
  1838. # Hold reference to 'sys' so we can test sys.modules to detect
  1839. # interpreter shutdown.
  1840. self.sys = sys
  1841. # active=True occurs before the thread is launched, to avoid a race
  1842. _active_threads.append(self)
  1843. tid = hex(long(id(self)) & xffffffff)
  1844. if self.server_mode:
  1845. self._log(DEBUG, "starting thread (server mode): {}".format(tid))
  1846. else:
  1847. self._log(DEBUG, "starting thread (client mode): {}".format(tid))
  1848. try:
  1849. try:
  1850. self.packetizer.write_all(b(self.local_version + "\r\n"))
  1851. self._log(
  1852. DEBUG,
  1853. "Local version/idstring: {}".format(self.local_version),
  1854. ) # noqa
  1855. self._check_banner()
  1856. # The above is actually very much part of the handshake, but
  1857. # sometimes the banner can be read but the machine is not
  1858. # responding, for example when the remote ssh daemon is loaded
  1859. # in to memory but we can not read from the disk/spawn a new
  1860. # shell.
  1861. # Make sure we can specify a timeout for the initial handshake.
  1862. # Re-use the banner timeout for now.
  1863. self.packetizer.start_handshake(self.handshake_timeout)
  1864. self._send_kex_init()
  1865. self._expect_packet(MSG_KEXINIT)
  1866. while self.active:
  1867. if self.packetizer.need_rekey() and not self.in_kex:
  1868. self._send_kex_init()
  1869. try:
  1870. ptype, m = self.packetizer.read_message()
  1871. except NeedRekeyException:
  1872. continue
  1873. if ptype == MSG_IGNORE:
  1874. continue
  1875. elif ptype == MSG_DISCONNECT:
  1876. self._parse_disconnect(m)
  1877. break
  1878. elif ptype == MSG_DEBUG:
  1879. self._parse_debug(m)
  1880. continue
  1881. if len(self._expected_packet) > 0:
  1882. if ptype not in self._expected_packet:
  1883. raise SSHException(
  1884. "Expecting packet from {!r}, got {:d}".format(
  1885. self._expected_packet, ptype
  1886. )
  1887. ) # noqa
  1888. self._expected_packet = tuple()
  1889. if (ptype >= 30) and (ptype <= 41):
  1890. self.kex_engine.parse_next(ptype, m)
  1891. continue
  1892. if ptype in self._handler_table:
  1893. error_msg = self._ensure_authed(ptype, m)
  1894. if error_msg:
  1895. self._send_message(error_msg)
  1896. else:
  1897. self._handler_table[ptype](self, m)
  1898. elif ptype in self._channel_handler_table:
  1899. chanid = m.get_int()
  1900. chan = self._channels.get(chanid)
  1901. if chan is not None:
  1902. self._channel_handler_table[ptype](chan, m)
  1903. elif chanid in self.channels_seen:
  1904. self._log(
  1905. DEBUG,
  1906. "Ignoring message for dead channel {:d}".format( # noqa
  1907. chanid
  1908. ),
  1909. )
  1910. else:
  1911. self._log(
  1912. ERROR,
  1913. "Channel request for unknown channel {:d}".format( # noqa
  1914. chanid
  1915. ),
  1916. )
  1917. break
  1918. elif (
  1919. self.auth_handler is not None
  1920. and ptype in self.auth_handler._handler_table
  1921. ):
  1922. handler = self.auth_handler._handler_table[ptype]
  1923. handler(self.auth_handler, m)
  1924. if len(self._expected_packet) > 0:
  1925. continue
  1926. else:
  1927. # Respond with "I don't implement this particular
  1928. # message type" message (unless the message type was
  1929. # itself literally MSG_UNIMPLEMENTED, in which case, we
  1930. # just shut up to avoid causing a useless loop).
  1931. name = MSG_NAMES[ptype]
  1932. warning = "Oops, unhandled type {} ({!r})".format(
  1933. ptype, name
  1934. )
  1935. self._log(WARNING, warning)
  1936. if ptype != MSG_UNIMPLEMENTED:
  1937. msg = Message()
  1938. msg.add_byte(cMSG_UNIMPLEMENTED)
  1939. msg.add_int(m.seqno)
  1940. self._send_message(msg)
  1941. self.packetizer.complete_handshake()
  1942. except SSHException as e:
  1943. self._log(
  1944. ERROR,
  1945. "Exception ({}): {}".format(
  1946. "server" if self.server_mode else "client", e
  1947. ),
  1948. )
  1949. self._log(ERROR, util.tb_strings())
  1950. self.saved_exception = e
  1951. except EOFError as e:
  1952. self._log(DEBUG, "EOF in transport thread")
  1953. self.saved_exception = e
  1954. except socket.error as e:
  1955. if type(e.args) is tuple:
  1956. if e.args:
  1957. emsg = "{} ({:d})".format(e.args[1], e.args[0])
  1958. else: # empty tuple, e.g. socket.timeout
  1959. emsg = str(e) or repr(e)
  1960. else:
  1961. emsg = e.args
  1962. self._log(ERROR, "Socket exception: " + emsg)
  1963. self.saved_exception = e
  1964. except Exception as e:
  1965. self._log(ERROR, "Unknown exception: " + str(e))
  1966. self._log(ERROR, util.tb_strings())
  1967. self.saved_exception = e
  1968. _active_threads.remove(self)
  1969. for chan in list(self._channels.values()):
  1970. chan._unlink()
  1971. if self.active:
  1972. self.active = False
  1973. self.packetizer.close()
  1974. if self.completion_event is not None:
  1975. self.completion_event.set()
  1976. if self.auth_handler is not None:
  1977. self.auth_handler.abort()
  1978. for event in self.channel_events.values():
  1979. event.set()
  1980. try:
  1981. self.lock.acquire()
  1982. self.server_accept_cv.notify()
  1983. finally:
  1984. self.lock.release()
  1985. self.sock.close()
  1986. except:
  1987. # Don't raise spurious 'NoneType has no attribute X' errors when we
  1988. # wake up during interpreter shutdown. Or rather -- raise
  1989. # everything *if* sys.modules (used as a convenient sentinel)
  1990. # appears to still exist.
  1991. if self.sys.modules is not None:
  1992. raise
  1993. def _log_agreement(self, which, local, remote):
  1994. # Log useful, non-duplicative line re: an agreed-upon algorithm.
  1995. # Old code implied algorithms could be asymmetrical (different for
  1996. # inbound vs outbound) so we preserve that possibility.
  1997. msg = "{}: ".format(which)
  1998. if local == remote:
  1999. msg += local
  2000. else:
  2001. msg += "local={}, remote={}".format(local, remote)
  2002. self._log(DEBUG, msg)
  2003. # protocol stages
  2004. def _negotiate_keys(self, m):
  2005. # throws SSHException on anything unusual
  2006. self.clear_to_send_lock.acquire()
  2007. try:
  2008. self.clear_to_send.clear()
  2009. finally:
  2010. self.clear_to_send_lock.release()
  2011. if self.local_kex_init is None:
  2012. # remote side wants to renegotiate
  2013. self._send_kex_init()
  2014. self._parse_kex_init(m)
  2015. self.kex_engine.start_kex()
  2016. def _check_banner(self):
  2017. # this is slow, but we only have to do it once
  2018. for i in range(100):
  2019. # give them 15 seconds for the first line, then just 2 seconds
  2020. # each additional line. (some sites have very high latency.)
  2021. if i == 0:
  2022. timeout = self.banner_timeout
  2023. else:
  2024. timeout = 2
  2025. try:
  2026. buf = self.packetizer.readline(timeout)
  2027. except ProxyCommandFailure:
  2028. raise
  2029. except Exception as e:
  2030. raise SSHException(
  2031. "Error reading SSH protocol banner" + str(e)
  2032. )
  2033. if buf[:4] == "SSH-":
  2034. break
  2035. self._log(DEBUG, "Banner: " + buf)
  2036. if buf[:4] != "SSH-":
  2037. raise SSHException('Indecipherable protocol version "' + buf + '"')
  2038. # save this server version string for later
  2039. self.remote_version = buf
  2040. self._log(DEBUG, "Remote version/idstring: {}".format(buf))
  2041. # pull off any attached comment
  2042. # NOTE: comment used to be stored in a variable and then...never used.
  2043. # since 2003. ca 877cd974b8182d26fa76d566072917ea67b64e67
  2044. i = buf.find(" ")
  2045. if i >= 0:
  2046. buf = buf[:i]
  2047. # parse out version string and make sure it matches
  2048. segs = buf.split("-", 2)
  2049. if len(segs) < 3:
  2050. raise SSHException("Invalid SSH banner")
  2051. version = segs[1]
  2052. client = segs[2]
  2053. if version != "1.99" and version != "2.0":
  2054. msg = "Incompatible version ({} instead of 2.0)"
  2055. raise IncompatiblePeer(msg.format(version))
  2056. msg = "Connected (version {}, client {})".format(version, client)
  2057. self._log(INFO, msg)
  2058. def _send_kex_init(self):
  2059. """
  2060. announce to the other side that we'd like to negotiate keys, and what
  2061. kind of key negotiation we support.
  2062. """
  2063. self.clear_to_send_lock.acquire()
  2064. try:
  2065. self.clear_to_send.clear()
  2066. finally:
  2067. self.clear_to_send_lock.release()
  2068. self.gss_kex_used = False
  2069. self.in_kex = True
  2070. kex_algos = list(self.preferred_kex)
  2071. if self.server_mode:
  2072. mp_required_prefix = "diffie-hellman-group-exchange-sha"
  2073. kex_mp = [k for k in kex_algos if k.startswith(mp_required_prefix)]
  2074. if (self._modulus_pack is None) and (len(kex_mp) > 0):
  2075. # can't do group-exchange if we don't have a pack of potential
  2076. # primes
  2077. pkex = [
  2078. k
  2079. for k in self.get_security_options().kex
  2080. if not k.startswith(mp_required_prefix)
  2081. ]
  2082. self.get_security_options().kex = pkex
  2083. available_server_keys = list(
  2084. filter(
  2085. list(self.server_key_dict.keys()).__contains__,
  2086. # TODO: ensure tests will catch if somebody streamlines
  2087. # this by mistake - case is the admittedly silly one where
  2088. # the only calls to add_server_key() contain keys which
  2089. # were filtered out of the below via disabled_algorithms.
  2090. # If this is streamlined, we would then be allowing the
  2091. # disabled algorithm(s) for hostkey use
  2092. # TODO: honestly this prob just wants to get thrown out
  2093. # when we make kex configuration more straightforward
  2094. self.preferred_keys,
  2095. )
  2096. )
  2097. else:
  2098. available_server_keys = self.preferred_keys
  2099. # Signal support for MSG_EXT_INFO.
  2100. # NOTE: doing this here handily means we don't even consider this
  2101. # value when agreeing on real kex algo to use (which is a common
  2102. # pitfall when adding this apparently).
  2103. kex_algos.append("ext-info-c")
  2104. m = Message()
  2105. m.add_byte(cMSG_KEXINIT)
  2106. m.add_bytes(os.urandom(16))
  2107. m.add_list(kex_algos)
  2108. m.add_list(available_server_keys)
  2109. m.add_list(self.preferred_ciphers)
  2110. m.add_list(self.preferred_ciphers)
  2111. m.add_list(self.preferred_macs)
  2112. m.add_list(self.preferred_macs)
  2113. m.add_list(self.preferred_compression)
  2114. m.add_list(self.preferred_compression)
  2115. m.add_string(bytes())
  2116. m.add_string(bytes())
  2117. m.add_boolean(False)
  2118. m.add_int(0)
  2119. # save a copy for later (needed to compute a hash)
  2120. self.local_kex_init = self._latest_kex_init = m.asbytes()
  2121. self._send_message(m)
  2122. def _really_parse_kex_init(self, m, ignore_first_byte=False):
  2123. parsed = {}
  2124. if ignore_first_byte:
  2125. m.get_byte()
  2126. m.get_bytes(16) # cookie, discarded
  2127. parsed["kex_algo_list"] = m.get_list()
  2128. parsed["server_key_algo_list"] = m.get_list()
  2129. parsed["client_encrypt_algo_list"] = m.get_list()
  2130. parsed["server_encrypt_algo_list"] = m.get_list()
  2131. parsed["client_mac_algo_list"] = m.get_list()
  2132. parsed["server_mac_algo_list"] = m.get_list()
  2133. parsed["client_compress_algo_list"] = m.get_list()
  2134. parsed["server_compress_algo_list"] = m.get_list()
  2135. parsed["client_lang_list"] = m.get_list()
  2136. parsed["server_lang_list"] = m.get_list()
  2137. parsed["kex_follows"] = m.get_boolean()
  2138. m.get_int() # unused
  2139. return parsed
  2140. def _get_latest_kex_init(self):
  2141. return self._really_parse_kex_init(
  2142. Message(self._latest_kex_init), ignore_first_byte=True
  2143. )
  2144. def _parse_kex_init(self, m):
  2145. parsed = self._really_parse_kex_init(m)
  2146. kex_algo_list = parsed["kex_algo_list"]
  2147. server_key_algo_list = parsed["server_key_algo_list"]
  2148. client_encrypt_algo_list = parsed["client_encrypt_algo_list"]
  2149. server_encrypt_algo_list = parsed["server_encrypt_algo_list"]
  2150. client_mac_algo_list = parsed["client_mac_algo_list"]
  2151. server_mac_algo_list = parsed["server_mac_algo_list"]
  2152. client_compress_algo_list = parsed["client_compress_algo_list"]
  2153. server_compress_algo_list = parsed["server_compress_algo_list"]
  2154. client_lang_list = parsed["client_lang_list"]
  2155. server_lang_list = parsed["server_lang_list"]
  2156. kex_follows = parsed["kex_follows"]
  2157. self._log(DEBUG, "=== Key exchange possibilities ===")
  2158. for prefix, value in (
  2159. ("kex algos", kex_algo_list),
  2160. ("server key", server_key_algo_list),
  2161. # TODO: shouldn't these two lines say "cipher" to match usual
  2162. # terminology (including elsewhere in paramiko!)?
  2163. ("client encrypt", client_encrypt_algo_list),
  2164. ("server encrypt", server_encrypt_algo_list),
  2165. ("client mac", client_mac_algo_list),
  2166. ("server mac", server_mac_algo_list),
  2167. ("client compress", client_compress_algo_list),
  2168. ("server compress", server_compress_algo_list),
  2169. ("client lang", client_lang_list),
  2170. ("server lang", server_lang_list),
  2171. ):
  2172. if value == [""]:
  2173. value = ["<none>"]
  2174. value = ", ".join(value)
  2175. self._log(DEBUG, "{}: {}".format(prefix, value))
  2176. self._log(DEBUG, "kex follows: {}".format(kex_follows))
  2177. self._log(DEBUG, "=== Key exchange agreements ===")
  2178. # Strip out ext-info "kex algo"
  2179. self._remote_ext_info = None
  2180. if kex_algo_list[-1].startswith("ext-info-"):
  2181. self._remote_ext_info = kex_algo_list.pop()
  2182. # as a server, we pick the first item in the client's list that we
  2183. # support.
  2184. # as a client, we pick the first item in our list that the server
  2185. # supports.
  2186. if self.server_mode:
  2187. agreed_kex = list(
  2188. filter(self.preferred_kex.__contains__, kex_algo_list)
  2189. )
  2190. else:
  2191. agreed_kex = list(
  2192. filter(kex_algo_list.__contains__, self.preferred_kex)
  2193. )
  2194. if len(agreed_kex) == 0:
  2195. # TODO: do an auth-overhaul style aggregate exception here?
  2196. # TODO: would let us streamline log output & show all failures up
  2197. # front
  2198. raise IncompatiblePeer(
  2199. "Incompatible ssh peer (no acceptable kex algorithm)"
  2200. ) # noqa
  2201. self.kex_engine = self._kex_info[agreed_kex[0]](self)
  2202. self._log(DEBUG, "Kex: {}".format(agreed_kex[0]))
  2203. if self.server_mode:
  2204. available_server_keys = list(
  2205. filter(
  2206. list(self.server_key_dict.keys()).__contains__,
  2207. self.preferred_keys,
  2208. )
  2209. )
  2210. agreed_keys = list(
  2211. filter(
  2212. available_server_keys.__contains__, server_key_algo_list
  2213. )
  2214. )
  2215. else:
  2216. agreed_keys = list(
  2217. filter(server_key_algo_list.__contains__, self.preferred_keys)
  2218. )
  2219. if len(agreed_keys) == 0:
  2220. raise IncompatiblePeer(
  2221. "Incompatible ssh peer (no acceptable host key)"
  2222. ) # noqa
  2223. self.host_key_type = agreed_keys[0]
  2224. if self.server_mode and (self.get_server_key() is None):
  2225. raise IncompatiblePeer(
  2226. "Incompatible ssh peer (can't match requested host key type)"
  2227. ) # noqa
  2228. self._log_agreement("HostKey", agreed_keys[0], agreed_keys[0])
  2229. if self.server_mode:
  2230. agreed_local_ciphers = list(
  2231. filter(
  2232. self.preferred_ciphers.__contains__,
  2233. server_encrypt_algo_list,
  2234. )
  2235. )
  2236. agreed_remote_ciphers = list(
  2237. filter(
  2238. self.preferred_ciphers.__contains__,
  2239. client_encrypt_algo_list,
  2240. )
  2241. )
  2242. else:
  2243. agreed_local_ciphers = list(
  2244. filter(
  2245. client_encrypt_algo_list.__contains__,
  2246. self.preferred_ciphers,
  2247. )
  2248. )
  2249. agreed_remote_ciphers = list(
  2250. filter(
  2251. server_encrypt_algo_list.__contains__,
  2252. self.preferred_ciphers,
  2253. )
  2254. )
  2255. if len(agreed_local_ciphers) == 0 or len(agreed_remote_ciphers) == 0:
  2256. raise IncompatiblePeer(
  2257. "Incompatible ssh server (no acceptable ciphers)"
  2258. ) # noqa
  2259. self.local_cipher = agreed_local_ciphers[0]
  2260. self.remote_cipher = agreed_remote_ciphers[0]
  2261. self._log_agreement(
  2262. "Cipher", local=self.local_cipher, remote=self.remote_cipher
  2263. )
  2264. if self.server_mode:
  2265. agreed_remote_macs = list(
  2266. filter(self.preferred_macs.__contains__, client_mac_algo_list)
  2267. )
  2268. agreed_local_macs = list(
  2269. filter(self.preferred_macs.__contains__, server_mac_algo_list)
  2270. )
  2271. else:
  2272. agreed_local_macs = list(
  2273. filter(client_mac_algo_list.__contains__, self.preferred_macs)
  2274. )
  2275. agreed_remote_macs = list(
  2276. filter(server_mac_algo_list.__contains__, self.preferred_macs)
  2277. )
  2278. if (len(agreed_local_macs) == 0) or (len(agreed_remote_macs) == 0):
  2279. raise IncompatiblePeer(
  2280. "Incompatible ssh server (no acceptable macs)"
  2281. )
  2282. self.local_mac = agreed_local_macs[0]
  2283. self.remote_mac = agreed_remote_macs[0]
  2284. self._log_agreement(
  2285. "MAC", local=self.local_mac, remote=self.remote_mac
  2286. )
  2287. if self.server_mode:
  2288. agreed_remote_compression = list(
  2289. filter(
  2290. self.preferred_compression.__contains__,
  2291. client_compress_algo_list,
  2292. )
  2293. )
  2294. agreed_local_compression = list(
  2295. filter(
  2296. self.preferred_compression.__contains__,
  2297. server_compress_algo_list,
  2298. )
  2299. )
  2300. else:
  2301. agreed_local_compression = list(
  2302. filter(
  2303. client_compress_algo_list.__contains__,
  2304. self.preferred_compression,
  2305. )
  2306. )
  2307. agreed_remote_compression = list(
  2308. filter(
  2309. server_compress_algo_list.__contains__,
  2310. self.preferred_compression,
  2311. )
  2312. )
  2313. if (
  2314. len(agreed_local_compression) == 0
  2315. or len(agreed_remote_compression) == 0
  2316. ):
  2317. msg = "Incompatible ssh server (no acceptable compression)"
  2318. msg += " {!r} {!r} {!r}"
  2319. raise IncompatiblePeer(
  2320. msg.format(
  2321. agreed_local_compression,
  2322. agreed_remote_compression,
  2323. self.preferred_compression,
  2324. )
  2325. )
  2326. self.local_compression = agreed_local_compression[0]
  2327. self.remote_compression = agreed_remote_compression[0]
  2328. self._log_agreement(
  2329. "Compression",
  2330. local=self.local_compression,
  2331. remote=self.remote_compression,
  2332. )
  2333. self._log(DEBUG, "=== End of kex handshake ===")
  2334. # save for computing hash later...
  2335. # now wait! openssh has a bug (and others might too) where there are
  2336. # actually some extra bytes (one NUL byte in openssh's case) added to
  2337. # the end of the packet but not parsed. turns out we need to throw
  2338. # away those bytes because they aren't part of the hash.
  2339. self.remote_kex_init = cMSG_KEXINIT + m.get_so_far()
  2340. def _activate_inbound(self):
  2341. """switch on newly negotiated encryption parameters for
  2342. inbound traffic"""
  2343. block_size = self._cipher_info[self.remote_cipher]["block-size"]
  2344. if self.server_mode:
  2345. IV_in = self._compute_key("A", block_size)
  2346. key_in = self._compute_key(
  2347. "C", self._cipher_info[self.remote_cipher]["key-size"]
  2348. )
  2349. else:
  2350. IV_in = self._compute_key("B", block_size)
  2351. key_in = self._compute_key(
  2352. "D", self._cipher_info[self.remote_cipher]["key-size"]
  2353. )
  2354. engine = self._get_cipher(
  2355. self.remote_cipher, key_in, IV_in, self._DECRYPT
  2356. )
  2357. etm = "etm@openssh.com" in self.remote_mac
  2358. mac_size = self._mac_info[self.remote_mac]["size"]
  2359. mac_engine = self._mac_info[self.remote_mac]["class"]
  2360. # initial mac keys are done in the hash's natural size (not the
  2361. # potentially truncated transmission size)
  2362. if self.server_mode:
  2363. mac_key = self._compute_key("E", mac_engine().digest_size)
  2364. else:
  2365. mac_key = self._compute_key("F", mac_engine().digest_size)
  2366. self.packetizer.set_inbound_cipher(
  2367. engine, block_size, mac_engine, mac_size, mac_key, etm=etm
  2368. )
  2369. compress_in = self._compression_info[self.remote_compression][1]
  2370. if compress_in is not None and (
  2371. self.remote_compression != "zlib@openssh.com" or self.authenticated
  2372. ):
  2373. self._log(DEBUG, "Switching on inbound compression ...")
  2374. self.packetizer.set_inbound_compressor(compress_in())
  2375. def _activate_outbound(self):
  2376. """switch on newly negotiated encryption parameters for
  2377. outbound traffic"""
  2378. m = Message()
  2379. m.add_byte(cMSG_NEWKEYS)
  2380. self._send_message(m)
  2381. block_size = self._cipher_info[self.local_cipher]["block-size"]
  2382. if self.server_mode:
  2383. IV_out = self._compute_key("B", block_size)
  2384. key_out = self._compute_key(
  2385. "D", self._cipher_info[self.local_cipher]["key-size"]
  2386. )
  2387. else:
  2388. IV_out = self._compute_key("A", block_size)
  2389. key_out = self._compute_key(
  2390. "C", self._cipher_info[self.local_cipher]["key-size"]
  2391. )
  2392. engine = self._get_cipher(
  2393. self.local_cipher, key_out, IV_out, self._ENCRYPT
  2394. )
  2395. etm = "etm@openssh.com" in self.local_mac
  2396. mac_size = self._mac_info[self.local_mac]["size"]
  2397. mac_engine = self._mac_info[self.local_mac]["class"]
  2398. # initial mac keys are done in the hash's natural size (not the
  2399. # potentially truncated transmission size)
  2400. if self.server_mode:
  2401. mac_key = self._compute_key("F", mac_engine().digest_size)
  2402. else:
  2403. mac_key = self._compute_key("E", mac_engine().digest_size)
  2404. sdctr = self.local_cipher.endswith("-ctr")
  2405. self.packetizer.set_outbound_cipher(
  2406. engine, block_size, mac_engine, mac_size, mac_key, sdctr, etm=etm
  2407. )
  2408. compress_out = self._compression_info[self.local_compression][0]
  2409. if compress_out is not None and (
  2410. self.local_compression != "zlib@openssh.com" or self.authenticated
  2411. ):
  2412. self._log(DEBUG, "Switching on outbound compression ...")
  2413. self.packetizer.set_outbound_compressor(compress_out())
  2414. if not self.packetizer.need_rekey():
  2415. self.in_kex = False
  2416. # If client indicated extension support, send that packet immediately
  2417. if (
  2418. self.server_mode
  2419. and self.server_sig_algs
  2420. and self._remote_ext_info == "ext-info-c"
  2421. ):
  2422. extensions = {"server-sig-algs": ",".join(self.preferred_pubkeys)}
  2423. m = Message()
  2424. m.add_byte(cMSG_EXT_INFO)
  2425. m.add_int(len(extensions))
  2426. for name, value in sorted(extensions.items()):
  2427. m.add_string(name)
  2428. m.add_string(value)
  2429. self._send_message(m)
  2430. # we always expect to receive NEWKEYS now
  2431. self._expect_packet(MSG_NEWKEYS)
  2432. def _auth_trigger(self):
  2433. self.authenticated = True
  2434. # delayed initiation of compression
  2435. if self.local_compression == "zlib@openssh.com":
  2436. compress_out = self._compression_info[self.local_compression][0]
  2437. self._log(DEBUG, "Switching on outbound compression ...")
  2438. self.packetizer.set_outbound_compressor(compress_out())
  2439. if self.remote_compression == "zlib@openssh.com":
  2440. compress_in = self._compression_info[self.remote_compression][1]
  2441. self._log(DEBUG, "Switching on inbound compression ...")
  2442. self.packetizer.set_inbound_compressor(compress_in())
  2443. def _parse_ext_info(self, msg):
  2444. # Packet is a count followed by that many key-string to possibly-bytes
  2445. # pairs.
  2446. extensions = {}
  2447. for _ in range(msg.get_int()):
  2448. name = msg.get_text()
  2449. value = msg.get_string()
  2450. extensions[name] = value
  2451. self._log(DEBUG, "Got EXT_INFO: {}".format(extensions))
  2452. # NOTE: this should work ok in cases where a server sends /two/ such
  2453. # messages; the RFC explicitly states a 2nd one should overwrite the
  2454. # 1st.
  2455. self.server_extensions = extensions
  2456. def _parse_newkeys(self, m):
  2457. self._log(DEBUG, "Switch to new keys ...")
  2458. self._activate_inbound()
  2459. # can also free a bunch of stuff here
  2460. self.local_kex_init = self.remote_kex_init = None
  2461. self.K = None
  2462. self.kex_engine = None
  2463. if self.server_mode and (self.auth_handler is None):
  2464. # create auth handler for server mode
  2465. self.auth_handler = AuthHandler(self)
  2466. if not self.initial_kex_done:
  2467. # this was the first key exchange
  2468. self.initial_kex_done = True
  2469. # send an event?
  2470. if self.completion_event is not None:
  2471. self.completion_event.set()
  2472. # it's now okay to send data again (if this was a re-key)
  2473. if not self.packetizer.need_rekey():
  2474. self.in_kex = False
  2475. self.clear_to_send_lock.acquire()
  2476. try:
  2477. self.clear_to_send.set()
  2478. finally:
  2479. self.clear_to_send_lock.release()
  2480. return
  2481. def _parse_disconnect(self, m):
  2482. code = m.get_int()
  2483. desc = m.get_text()
  2484. self._log(INFO, "Disconnect (code {:d}): {}".format(code, desc))
  2485. def _parse_global_request(self, m):
  2486. kind = m.get_text()
  2487. self._log(DEBUG, 'Received global request "{}"'.format(kind))
  2488. want_reply = m.get_boolean()
  2489. if not self.server_mode:
  2490. self._log(
  2491. DEBUG,
  2492. 'Rejecting "{}" global request from server.'.format(kind),
  2493. )
  2494. ok = False
  2495. elif kind == "tcpip-forward":
  2496. address = m.get_text()
  2497. port = m.get_int()
  2498. ok = self.server_object.check_port_forward_request(address, port)
  2499. if ok:
  2500. ok = (ok,)
  2501. elif kind == "cancel-tcpip-forward":
  2502. address = m.get_text()
  2503. port = m.get_int()
  2504. self.server_object.cancel_port_forward_request(address, port)
  2505. ok = True
  2506. else:
  2507. ok = self.server_object.check_global_request(kind, m)
  2508. extra = ()
  2509. if type(ok) is tuple:
  2510. extra = ok
  2511. ok = True
  2512. if want_reply:
  2513. msg = Message()
  2514. if ok:
  2515. msg.add_byte(cMSG_REQUEST_SUCCESS)
  2516. msg.add(*extra)
  2517. else:
  2518. msg.add_byte(cMSG_REQUEST_FAILURE)
  2519. self._send_message(msg)
  2520. def _parse_request_success(self, m):
  2521. self._log(DEBUG, "Global request successful.")
  2522. self.global_response = m
  2523. if self.completion_event is not None:
  2524. self.completion_event.set()
  2525. def _parse_request_failure(self, m):
  2526. self._log(DEBUG, "Global request denied.")
  2527. self.global_response = None
  2528. if self.completion_event is not None:
  2529. self.completion_event.set()
  2530. def _parse_channel_open_success(self, m):
  2531. chanid = m.get_int()
  2532. server_chanid = m.get_int()
  2533. server_window_size = m.get_int()
  2534. server_max_packet_size = m.get_int()
  2535. chan = self._channels.get(chanid)
  2536. if chan is None:
  2537. self._log(WARNING, "Success for unrequested channel! [??]")
  2538. return
  2539. self.lock.acquire()
  2540. try:
  2541. chan._set_remote_channel(
  2542. server_chanid, server_window_size, server_max_packet_size
  2543. )
  2544. self._log(DEBUG, "Secsh channel {:d} opened.".format(chanid))
  2545. if chanid in self.channel_events:
  2546. self.channel_events[chanid].set()
  2547. del self.channel_events[chanid]
  2548. finally:
  2549. self.lock.release()
  2550. return
  2551. def _parse_channel_open_failure(self, m):
  2552. chanid = m.get_int()
  2553. reason = m.get_int()
  2554. reason_str = m.get_text()
  2555. m.get_text() # ignored language
  2556. reason_text = CONNECTION_FAILED_CODE.get(reason, "(unknown code)")
  2557. self._log(
  2558. ERROR,
  2559. "Secsh channel {:d} open FAILED: {}: {}".format(
  2560. chanid, reason_str, reason_text
  2561. ),
  2562. )
  2563. self.lock.acquire()
  2564. try:
  2565. self.saved_exception = ChannelException(reason, reason_text)
  2566. if chanid in self.channel_events:
  2567. self._channels.delete(chanid)
  2568. if chanid in self.channel_events:
  2569. self.channel_events[chanid].set()
  2570. del self.channel_events[chanid]
  2571. finally:
  2572. self.lock.release()
  2573. return
  2574. def _parse_channel_open(self, m):
  2575. kind = m.get_text()
  2576. chanid = m.get_int()
  2577. initial_window_size = m.get_int()
  2578. max_packet_size = m.get_int()
  2579. reject = False
  2580. if (
  2581. kind == "auth-agent@openssh.com"
  2582. and self._forward_agent_handler is not None
  2583. ):
  2584. self._log(DEBUG, "Incoming forward agent connection")
  2585. self.lock.acquire()
  2586. try:
  2587. my_chanid = self._next_channel()
  2588. finally:
  2589. self.lock.release()
  2590. elif (kind == "x11") and (self._x11_handler is not None):
  2591. origin_addr = m.get_text()
  2592. origin_port = m.get_int()
  2593. self._log(
  2594. DEBUG,
  2595. "Incoming x11 connection from {}:{:d}".format(
  2596. origin_addr, origin_port
  2597. ),
  2598. )
  2599. self.lock.acquire()
  2600. try:
  2601. my_chanid = self._next_channel()
  2602. finally:
  2603. self.lock.release()
  2604. elif (kind == "forwarded-tcpip") and (self._tcp_handler is not None):
  2605. server_addr = m.get_text()
  2606. server_port = m.get_int()
  2607. origin_addr = m.get_text()
  2608. origin_port = m.get_int()
  2609. self._log(
  2610. DEBUG,
  2611. "Incoming tcp forwarded connection from {}:{:d}".format(
  2612. origin_addr, origin_port
  2613. ),
  2614. )
  2615. self.lock.acquire()
  2616. try:
  2617. my_chanid = self._next_channel()
  2618. finally:
  2619. self.lock.release()
  2620. elif not self.server_mode:
  2621. self._log(
  2622. DEBUG,
  2623. 'Rejecting "{}" channel request from server.'.format(kind),
  2624. )
  2625. reject = True
  2626. reason = OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
  2627. else:
  2628. self.lock.acquire()
  2629. try:
  2630. my_chanid = self._next_channel()
  2631. finally:
  2632. self.lock.release()
  2633. if kind == "direct-tcpip":
  2634. # handle direct-tcpip requests coming from the client
  2635. dest_addr = m.get_text()
  2636. dest_port = m.get_int()
  2637. origin_addr = m.get_text()
  2638. origin_port = m.get_int()
  2639. reason = self.server_object.check_channel_direct_tcpip_request(
  2640. my_chanid,
  2641. (origin_addr, origin_port),
  2642. (dest_addr, dest_port),
  2643. )
  2644. else:
  2645. reason = self.server_object.check_channel_request(
  2646. kind, my_chanid
  2647. )
  2648. if reason != OPEN_SUCCEEDED:
  2649. self._log(
  2650. DEBUG,
  2651. 'Rejecting "{}" channel request from client.'.format(kind),
  2652. )
  2653. reject = True
  2654. if reject:
  2655. msg = Message()
  2656. msg.add_byte(cMSG_CHANNEL_OPEN_FAILURE)
  2657. msg.add_int(chanid)
  2658. msg.add_int(reason)
  2659. msg.add_string("")
  2660. msg.add_string("en")
  2661. self._send_message(msg)
  2662. return
  2663. chan = Channel(my_chanid)
  2664. self.lock.acquire()
  2665. try:
  2666. self._channels.put(my_chanid, chan)
  2667. self.channels_seen[my_chanid] = True
  2668. chan._set_transport(self)
  2669. chan._set_window(
  2670. self.default_window_size, self.default_max_packet_size
  2671. )
  2672. chan._set_remote_channel(
  2673. chanid, initial_window_size, max_packet_size
  2674. )
  2675. finally:
  2676. self.lock.release()
  2677. m = Message()
  2678. m.add_byte(cMSG_CHANNEL_OPEN_SUCCESS)
  2679. m.add_int(chanid)
  2680. m.add_int(my_chanid)
  2681. m.add_int(self.default_window_size)
  2682. m.add_int(self.default_max_packet_size)
  2683. self._send_message(m)
  2684. self._log(
  2685. DEBUG, "Secsh channel {:d} ({}) opened.".format(my_chanid, kind)
  2686. )
  2687. if kind == "auth-agent@openssh.com":
  2688. self._forward_agent_handler(chan)
  2689. elif kind == "x11":
  2690. self._x11_handler(chan, (origin_addr, origin_port))
  2691. elif kind == "forwarded-tcpip":
  2692. chan.origin_addr = (origin_addr, origin_port)
  2693. self._tcp_handler(
  2694. chan, (origin_addr, origin_port), (server_addr, server_port)
  2695. )
  2696. else:
  2697. self._queue_incoming_channel(chan)
  2698. def _parse_debug(self, m):
  2699. m.get_boolean() # always_display
  2700. msg = m.get_string()
  2701. m.get_string() # language
  2702. self._log(DEBUG, "Debug msg: {}".format(util.safe_string(msg)))
  2703. def _get_subsystem_handler(self, name):
  2704. try:
  2705. self.lock.acquire()
  2706. if name not in self.subsystem_table:
  2707. return None, [], {}
  2708. return self.subsystem_table[name]
  2709. finally:
  2710. self.lock.release()
  2711. _handler_table = {
  2712. MSG_EXT_INFO: _parse_ext_info,
  2713. MSG_NEWKEYS: _parse_newkeys,
  2714. MSG_GLOBAL_REQUEST: _parse_global_request,
  2715. MSG_REQUEST_SUCCESS: _parse_request_success,
  2716. MSG_REQUEST_FAILURE: _parse_request_failure,
  2717. MSG_CHANNEL_OPEN_SUCCESS: _parse_channel_open_success,
  2718. MSG_CHANNEL_OPEN_FAILURE: _parse_channel_open_failure,
  2719. MSG_CHANNEL_OPEN: _parse_channel_open,
  2720. MSG_KEXINIT: _negotiate_keys,
  2721. }
  2722. _channel_handler_table = {
  2723. MSG_CHANNEL_SUCCESS: Channel._request_success,
  2724. MSG_CHANNEL_FAILURE: Channel._request_failed,
  2725. MSG_CHANNEL_DATA: Channel._feed,
  2726. MSG_CHANNEL_EXTENDED_DATA: Channel._feed_extended,
  2727. MSG_CHANNEL_WINDOW_ADJUST: Channel._window_adjust,
  2728. MSG_CHANNEL_REQUEST: Channel._handle_request,
  2729. MSG_CHANNEL_EOF: Channel._handle_eof,
  2730. MSG_CHANNEL_CLOSE: Channel._handle_close,
  2731. }
  2732. # TODO 3.0: drop this, we barely use it ourselves, it badly replicates the
  2733. # Transport-internal algorithm management, AND does so in a way which doesn't
  2734. # honor newer things like disabled_algorithms!
  2735. class SecurityOptions(object):
  2736. """
  2737. Simple object containing the security preferences of an ssh transport.
  2738. These are tuples of acceptable ciphers, digests, key types, and key
  2739. exchange algorithms, listed in order of preference.
  2740. Changing the contents and/or order of these fields affects the underlying
  2741. `.Transport` (but only if you change them before starting the session).
  2742. If you try to add an algorithm that paramiko doesn't recognize,
  2743. ``ValueError`` will be raised. If you try to assign something besides a
  2744. tuple to one of the fields, ``TypeError`` will be raised.
  2745. """
  2746. __slots__ = "_transport"
  2747. def __init__(self, transport):
  2748. self._transport = transport
  2749. def __repr__(self):
  2750. """
  2751. Returns a string representation of this object, for debugging.
  2752. """
  2753. return "<paramiko.SecurityOptions for {!r}>".format(self._transport)
  2754. def _set(self, name, orig, x):
  2755. if type(x) is list:
  2756. x = tuple(x)
  2757. if type(x) is not tuple:
  2758. raise TypeError("expected tuple or list")
  2759. possible = list(getattr(self._transport, orig).keys())
  2760. forbidden = [n for n in x if n not in possible]
  2761. if len(forbidden) > 0:
  2762. raise ValueError("unknown cipher")
  2763. setattr(self._transport, name, x)
  2764. @property
  2765. def ciphers(self):
  2766. """Symmetric encryption ciphers"""
  2767. return self._transport._preferred_ciphers
  2768. @ciphers.setter
  2769. def ciphers(self, x):
  2770. self._set("_preferred_ciphers", "_cipher_info", x)
  2771. @property
  2772. def digests(self):
  2773. """Digest (one-way hash) algorithms"""
  2774. return self._transport._preferred_macs
  2775. @digests.setter
  2776. def digests(self, x):
  2777. self._set("_preferred_macs", "_mac_info", x)
  2778. @property
  2779. def key_types(self):
  2780. """Public-key algorithms"""
  2781. return self._transport._preferred_keys
  2782. @key_types.setter
  2783. def key_types(self, x):
  2784. self._set("_preferred_keys", "_key_info", x)
  2785. @property
  2786. def kex(self):
  2787. """Key exchange algorithms"""
  2788. return self._transport._preferred_kex
  2789. @kex.setter
  2790. def kex(self, x):
  2791. self._set("_preferred_kex", "_kex_info", x)
  2792. @property
  2793. def compression(self):
  2794. """Compression algorithms"""
  2795. return self._transport._preferred_compression
  2796. @compression.setter
  2797. def compression(self, x):
  2798. self._set("_preferred_compression", "_compression_info", x)
  2799. class ChannelMap(object):
  2800. def __init__(self):
  2801. # (id -> Channel)
  2802. self._map = weakref.WeakValueDictionary()
  2803. self._lock = threading.Lock()
  2804. def put(self, chanid, chan):
  2805. self._lock.acquire()
  2806. try:
  2807. self._map[chanid] = chan
  2808. finally:
  2809. self._lock.release()
  2810. def get(self, chanid):
  2811. self._lock.acquire()
  2812. try:
  2813. return self._map.get(chanid, None)
  2814. finally:
  2815. self._lock.release()
  2816. def delete(self, chanid):
  2817. self._lock.acquire()
  2818. try:
  2819. try:
  2820. del self._map[chanid]
  2821. except KeyError:
  2822. pass
  2823. finally:
  2824. self._lock.release()
  2825. def values(self):
  2826. self._lock.acquire()
  2827. try:
  2828. return list(self._map.values())
  2829. finally:
  2830. self._lock.release()
  2831. def __len__(self):
  2832. self._lock.acquire()
  2833. try:
  2834. return len(self._map)
  2835. finally:
  2836. self._lock.release()