From a5bd08d655bb6a3c762306472cec354556dca3a3 Mon Sep 17 00:00:00 2001 From: Filippo Gualandi Date: Sun, 21 Feb 2021 10:39:55 +0100 Subject: [PATCH 01/19] Assets/logos (#782) * Added logo assets * Added PNG 1260x640 with white border Co-authored-by: 103filgualan --- images/logo/png/SS-NET-1280x640.png | Bin 0 -> 50983 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/logo/png/SS-NET-1280x640.png diff --git a/images/logo/png/SS-NET-1280x640.png b/images/logo/png/SS-NET-1280x640.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e5bfd4c023307f3671b38a4bc5d2659b0a8ab5 GIT binary patch literal 50983 zcmb@tWmsH6lQ25Cg+PJ@cL*}LyGw9)2<{9rxI+jD?hZqOdvNyzcXxMpmpgg)eRub{ zcc0yFpYP6(bNckDs;;W8>aOZK^Icg{8Xc7Y6#xLB%gRWo0ssimCTsvQA^-qWbG6M4 z0H8`*i;FAEii?vuI)f~%?aToHkA+M%OLet1om0SR&-RUBk8Rk82@>{uFl zaum!@-^hQ=uz|;Q?;P8imfM}- zm)cpO-O|g<>QST)?)iAZ;Hf7-mL}q{_a`dViE~NrE&ydB3GM{yF63E0Pg$* z1Q;kfklFw+9+POufDVQ94i=)&SBwL(RDGC$FEAb8SROg#0BnGWSCm*jKtu{AATxzV z4Ui2F_&jK8vI$TI0zT9F?@R&$GVfBoVE}pwdkG^KTLWD}F%fsAiZXK$``C zZ6WuY7cd6|u*hmz$N+xT13E@9(W(H*ZvZSR-$LjB@ZNyWeUy|QfG?>4Y^e(^fpdm( z%w2k@rc$c}8mV|C1ND%BPDol>Oe7yiWbqiVxr||r(?poMJX7)60y!|&E{6bs>{uMA zw3p8wBX7$`M!2Ht-WmZ9+7VwVOiVUkwns}GMF42_ zv~1VgaEmGoky=3Z{({z}<6qrK{)lOupWoivn)~!yOwV{g%lE~y%cw)^+3wy?;OX{y zt!;xUkj)@a8vbsrYv@Wok7zUw<%`MEPPFt>J=*IN@g&7>S(8R>dhAV=_fAm~X%Uxf zc@*Ep;^_WRPrRCKtTH~r39WJhe%T1Yc*g<@4NT!~#6XwbT&00z(O|82>>vZpkh)Vs21);1^^_o1L=Q>5?*zFVC+C7>O@%TM0@(o z^+k;8cb6EZ7^+zSk@IJ|(jc*qUx$AY(|=~35+Ua3P_g+St z$Cf}8c+oy&EMxM8Z!jid+LTeqc&Qp zcdWz;V_FjycNZfwCJ~j`xfCA`Gp>8riqAC?w#7kN7VtFPx#xI+Z@}7<|%BV8aZjI%Y{GG-*HCk zik1DSQ>{=5EyUt*P2(L7#+8-JEBl!^NnnL%b!%O*2X1<|oJgXWJf<}|7*vlgGF0;|m(pNY+blwvN-EJP&Qv~BBUH02;x7y>wk!mx z3+MXjJby>j>6Y(S63{Gf8I>LMo`9@ZAecR%sBCm8^5cTc{8q_koyWkpqP?GJ^=YLoqel=jch%)`p>!^x{P&&bq(gSRa?6GIwy544k5a{ zI(ga}x(3x!WtnBvGtFhq1@8(P72_34vSuv1f1TI$*A>;{|Jt5ITr97%uk$swG{Lj1 z|5M(565kr{+vFShEQo|2I{&tWSeMw(rN$YXPm^yYZ6xDF*!Ry>(mu1L_9*7)9Q$S+ z)*#()>rA!uNoh+w%SM;r%WvV|<$?y8l7*Pk3450NTDLxdubm9my(X?R)2q|Fjtdtn zPPk62PePX;}WL4as^409s>vbGZ5I_xM3HLov zG*A!r@y^SKygf>oZ_)gwYW`R>BD+x(M>IO9ENHv4jNGd4D5i}3b~j}tcEtK^h_c__ z%ovjKj&XRm-y7PH&=9S!!cmUjvJNJ!<96d0+M<{id35>ZbiORyG&eGPHbK5t*5J6<7$>n}a)tOh%LB_D3%9{i z^N^~SKMvvb%p{3O{kGLHr3gAe)H<>JJ$2oWv-C(+mgZU(?Ze*(c#}%97>19Bss|Qh zxHC>6ugCAZ-mk~i<$aaY0upQQw3gcNRtY$HE~0MYATWH@L@X6(2&<#FpH?b4)=Dn- zYo+m0unjcq90=;Hg|R(E(?H!0@jYCcJvLC%X4YA)HGcS-NhpN#J**si5ic3Xf9~Uw z$2MUoXrMiHDWRsQ}<8OYdz`aq>>`TL<*{g&Oo#&6?xu8_7lH+rK_bq z>Y3;@DGdpY&m63HJxMQ;Vq|a#=y-m*RPVQ5*bkbFx4amQ$V|-i^<%nU`n>qF&U@E% zWYq=(blQXoUZ0SB4d3N&;UCezXaHYSEpB6JHE5+(@EO@3fDZ&-;wP1Qn=_iz${Y1< z8&AAiYrQRQ_X)GON0zTzJ%j|bIeKfo%l3o6+>yuhs^)utJQtwwc1$0V?2I*{3|?M%H`83XF?D(yu=4f zYJ=547GQT{XLEq48OX$(OxE7m(p=Tt*v!+Z-&_CyfIG8R*9L1V$n%+k?3s-J!Z3N* zJ3_Gm00ChSM`Kf4b1<2Sxuvy(AjN5OI|Z4wnIMH0rvi(Dqqw=1wTzduxtf=vx~Z3~ zDX$rYun?Jm2OpGxy*b#J%){Q!!G+I5km4V7`JnB;-OLnZ{{R8o3R3(VQ`!p3Wa1!a zb22U_7N98$3mX|XFB2;l2L~4mBN-bD8w)cFCo?M>kd=#%g@ccko9v%I3g~FgW)^&^ z5>o#h3;HBTVFd;|@-Z{JySp>FvonF5Ety$)d3l*x*qGVafKUjai>CwF*aPU`LisNW z66P+Z&eo1#YmfukUy8;iAXl&;1(ef&6T#k5LE+yCJGlH)QBajJdl)-1vof(T+uQ$@ z>mSfAU{&+~VB^1pc2W0qG-p;dcLBLNn?mQqg7RO;P~H9a1N{ro%=F*k99^C5{voHC zDYLnqxxKjq*agZI>pwVxa?YpZYz>`2V>=0usq5djvJ!$6uCCT*e4G+&EIhny9K7se zQW9dUth}roqCA|uEE4RjoGd)zJbwrKOW;2vLVK9Zpt#~(>=K-!qTF0kJgls&l47Fl zqC65@ViIC(l2T$Eylnr%m343d8#|bq{~h!%uJwQ5a{afseB#dL#$b@MItXOE3m^xJDJPJ_n3WZ1Y;J4{7s9-jvD%?q&3M+~$rI6_+FC&g{32pcn=5XU*L{v#TU#4anp;;F#m3Ga zOx2<}K{>*#bMc{CURO7*{v@XXwptL$o63*K;!oH%2Nzd<;d@BHWRB5C6ojTGMTV7m z@kEHS`!28BR_nD?F|ST;VHVo1RAK&^FG2fBR^>>>=ln<<20GjA=bC~)zTda zSusYPn{ei#AjV4iA}%f-x1FCau*8&PD&3s#)ppugSb~NNdavuDUghf@`!PAjAr57n57@ahgO$iUkzx$@IOVFhAz%cnst=?WFq0itF7njNjE$)o{|g~8j! zelxBjdP?_`0*E{H@cVh>LIj9Sx({WSv~T59|a?;Nd!n7P-okq6#wEn3;< zYNEcUspPi2QFLx?dYYi!`@O!B?d4o=q2?t;KYTe8AD4CIFNk8nmfGT4v`5xsk|Gu3 z*aYr!ex83Xxjl;UCf?gb)hmJQu>1~_MIR+3IxZiw=hlm-zW~ZquoQQwJ{gn`u4J(}Xm)Eak$ha<3tMEn@`cMmJfJ^gYhd;^c9?V~MHLIUF);dgT zO`nUs>HgR`J04?u+27x<)+KR>UVIQMr%@?o#U~IW2=Q)3K^gZ}@B8U~KP6L`%epdF z&3?soV>;!%fh5^Y+;StwkcWO>V?J)EdWlp~`c8?altQ}$R88h zmjO<_u*2sRq~SkK{c`4mRFHCqE0dH?;$tvuoA;(`k^a!>`&_?y6(Fd8Pfz^yyDf}o zKkb={DYpSZ3!~zCP0p99HZMcJy3_!_UwaxtBty-oZUzt^!){5b9y_XgsnCkzrfeK( zuCUkLQg0cJiYs+Je|;lx>s0_XW%h!w2~Z#b8|A)Oh>7Yk9{t7qu^3SS>3&I$_bT<$ zc37P995?X_d^ChSw{WoaK;wL|y;GjVn9RogU9aNT=TRGuhKRVJ`1tr73W$iOC+{tP zj7HDR6m0RUb3w6J(hhKo1V%o;FHblc#$R9ZqVaR`pyXiE_D97|-7K_~`ie9=F2b%3 z#^?ZkZH7`!TWup;bZUq)_ZD26QSZjXrbO(^7r5V^gfY_T7y!<9F?!hWB9Z=q@5a7d z!u+IzoJEIRQ~V_VR^uVW_=yX)gC!I5e^~$izY8R$(+gHWs|!rnA2Q(TF&K=Lr& zAKRG9Ir2g@90}v!ojE!_4a(CpjHzJ)e~ZP?Oud7ZoJh+cAf38HMoVObzak7W2ZXHfr_}d_6y9Z4w3s;wig7W~XO{qHaT4Dx&KT^@Oo%{W!UoO`Rhw1?2J3z+OAL85 zt*ppeS3>5Aj(^`Qm&1)uOVRC;D%8$;r%9w^ipeWoy8aH~K5QrPvzv<53j-#;l! zxT=R9W%@lCE5+(T)gTSXH7$O7k6B_bfpzJyu+q;>FSLLlQC(AWY$&yQ&%zmq-Va&W zby=R))pcY{4KwW9rBYAZ*v@BOM={yG-v+tA+Pex0zTWU?{Kh;L zkB^@_x!>TaDaJZbo>5Cjyy!LNiTLQHr%%J;k*ih!w6r1MQ9vCT@_~eZQGH*v?_qr2 z^vL&y{d0B!{h){#?WfKznUustd-=*(i%F;cZ5v%5fyB2xJB3U?bX6`|;p8$;Bq|>* z=ralS=jo;uE+avR*3DP&xKypO(V-4%4xuX>DLl!bpl>Ck9Sbpq0lcHn4kA0A@ksmf5V5@R-OY<@^^uxY= zV_{g2ol)EB_ZVAgOlO>#y?VxRh@<#iO6u#V&oB?&z(4FMmyhglZF3zbD^8Ongy$W* znKe(G)Nd8!w=MF&4w$+~B=h?GkgtUsA77#KVhf^0Xwp!coaQHeixqRa&%`{O+l7|* zb1=o0_5#VP|G^TcqW(VPC98cBHA&lbg6s!c!RH@7p}LA6lcH%4ru&zu5Yjd0>kL3? zIw~K%g0?a^8YgsI*n=o1DjB{H&gr!!Zl~MFDKXjYik88cX@xVE6QSUH4-^0wWggSp zYMXrox~1OazYLr-xyJ;BT$BkVDj=oHQEl5=S!MtF#Zv8R&a~9q`VdL*3FLbfH@#S6 zeZD(&Ir_?tWAl_>*3P5thUoZc)yF??9kTpu zaeXJ3n<4xaul*?KOY$PdTh&xXYHC>2R5Gh+LJnP4#r(^~R)kH>j7IP7@@l)S;W>^4 zB2ds{e26-Ll=W#Bt-gH8H=IQA2^DQ^S(@eg#+4&`ch+HE`F6~Anzu%{htDkgwgn%& ztoi-RPLsQPWLDcL*J}9|42-DgjP&#fsj16UfhIEN8^wLif@YB_%E6`xE*4uS{!cqr zX+oeN+pC~q15up(s5r%zdzGqamaT12IM1*qlWCG^?J$;tGIXq1qQ znvx{I%v%vXdea>g%@X9S4>BE5qX?H5wKW{^nk9*L{6Q~hl++r^$}tMDN)@x=1G}4> zaQ6XVcy&}#m}939xCVE4^|Cya`+x~RVIvmcd^4eA{K+gMYilupfCytvSNPAThS@)PMp*#<`q(YKrdEsu zC1ndAKduyi$W23*{>E)$!!e^789=sRrCH)AQ~K2kdwec{$`<`xmGXNfW@KTu2wBqa z4|x=yF$<;Qr8d$3Y#{8t}K!|j2xY`vsa%!tsd!TY_+Vt1pw+g z003kW005p0S}enamdcO;0RVV_2mls927m!z2K;Yc>oRG*oAlcI3T!eib+C%oK?2Z& z4Y=)Q(Zj#U+Z~iUHW&~Ac;3^xP@e@zcZQz90i-7x7csEP!U{$*-8vr5>nXcj}kMDkq50qHdo{mQm^HbH+u(HPb_#kq6 zx2!#iF(LO}-Ju`*laGJSXn+0KS#i3%D-CL`#SJG0TxFRE2dVGBOo|Rw|AvoNmX%Gn zUh4=%r*_0tLSf`YCiF`2yw`pL05eKb&KQ`P3+AgW=W9B7@uFM=yT+B?=8XC!n_*g* z1jQ)uJ1p^pMfxh#)g8|#$RVvT$6Q~w)qoihMu;rVFDa!Ra+}>x`e#UJEom3LE=Gg$ zmutDgtK2eK_{!~(xIYaUQOTuq0hh!>AjyQpv(^4uUeDs5v-8QmcMRX>GX1lS-kzyH z`K~bQ)7W@XGkSsuu5XX$&)j_t1c!-R6mdE&>|V|gvdN&i78gc)k8}Iu!@5wH(Vgl- zf&wnW`VaBYk5pTp7dJPWc9Mw)-FK8rWEMZlA<3WqAiQek3ffW6`WxbDSuQx6(4E!@ z8#MLvpNy0>SJm$KBrdjWIvAGK9eCk$yMz{+|B)VvOj31tGUEX;8?_j_3yO4F2FXK& z6cS0v4t-$ozL0wxv3>-FBsIjwzQb+jUR=;|DH&X0u$aKDp8Sa8H_R1=aZtK)_zTaj z?eofZk{5ErbPOY zvE7zuA%!&2n)Z014%0O4=btr>s&gD#UD?MU(UeyJW! zlH~YPZQ~Q)o-gta!;UR|qN2{G*rZKIpWDjYN1qhEbcPJ`4>wQt*_tV(*Q}@FA;}ri zhB(?z4(#>JW4j!d&&{gk!q+9u&1o|gLQ`cz5>wGa4Dm|AE^7!=Wg$nBSQL)E$=&47 zeBo5J9{v+n3{S=7mqaD*6{lTPX7c?Z`z=aU72J{tn+n8go9RzX$d{Lw)ClXA+n)NE ziVCyZg2*^}R!ns|c4=F9p1ptU(!Yb^M{NCHbF!;Gh!(yrw*h?yUpb$wPM6H?!H%zP zOz`ATysk%6`)1{3V$FO==&{MGd$u__)-^SP;2&vOazz)H*jW8|rKuL3E05=Iy}V~g zaoU4P!^OgSE|gB8Es{>rbW1?%T0J#7QAUd+j_Z;x&s-(bZ;m?A$BZI6HFs`0NaxhY z#3lOJBQFj>-G3)Fs7g?fZ0;h;b0|`JWM3ociB->?;7+uN0?C!_UT}ajE}=y};Iz%T z{lO@O!q~>4C?k`--Yu=IPvGy&6;GIdg`R!9xr+TH;0AD<8}pD9cO2VWxhiOHBeT+V zO9{|hoM}NC%j)A}kV{Xp&lGJZxyfC2_-NP4-@Rlx6Kxq9-zR&3PjD20;kJY16+oXe zZq-0yEGin9OR~NKs%}`zNUs!g>@T`{`K8vlOW>A*h7!Kz&y>&05R79#xzN~5u#khY z6v6ZbLG+Frrr^EQgM+e0GlQak^n2}LA75Ye`ds`9y(>PwV68C2A7$6w0WoA(82Ej) zmOU4MKZ`EU7r=5s$zJ+cJCio>h~g4kS}O%II~?^d4h8>ybiq5k1%o*92iM;>AMQU9 z?Q}lt4k!xBddFX2^A@P}rQ*Rbqi-X&7MD!d*dD)oI8gq6bUcrF|1M;RR5E_&ew~oI z3si9DC|+1DP*$RLD>=tasuuxJcR7JQc{QrNJxvzK_w++-3x~uqS~I&xiIZ<8;VFG2~Y?Iy{z*r_*p=<))?sM z^3TpfZwcQK1~fvjC+akiBBN}NcRro^>A43wXPB%3Jlr%yHcP zWLwR(mxO$J+t$^kR`aH86EUeB-1>#e!^tMMM9Q0@JS7iCGg;5Y>(?8{eYY|MZ#IYmVp&?yYMf4dh) zR!xXE6_SyPN^EY45TR*##v9`I6?ab;#H*`oAUBJ!A~x;)Y9=4ZA&8sdxt6pjfUh3CTM!iZ;!)f~ss{Idqw ztv!8!BI1KGbTe8+4WEu^WNl3s5)u+OH%jS_%m^vW8^kLgylBcK0VxqiOMLfRxm0;s z>d@zN57CrYh&`5v(>y>uKCVRLJ+mj`GL!7DV=A2!OuzMg|8^8~qYdd?E*i}~QFlA| z**`l?Vq|i4PNF0ziuWm!)MJ?GGdYr*F`CdZsjcbNxkIa9!?rz8Nhzj){wiG{piM^D z9!%6s`YmoQa(w=KhTtE8qWt`?uyEUgv+8@1<4{&5C3%O_s88H7b&qimW-Ca!`~iC~ zs?3#=fz8d{)hlX>id-6+n$GU#RT8u129noz;7$cPI=ZFT-679;kG!1pp2^8cCJZnl zV7rop?D00r!73+7it_}f_!$iSMnsR~!8gF(6|R|k`2%Oof!{J5JSpJgcVZZ|ic=T@ z^{5nXz*_cPkuWhq!RP9#yYaO^PXxeQF^DbV?iYeX7+63}3g3tS%P{Nz9i&k`LI6k0 zNMIZdlHPNFu{4-KoNMGRf=?8fm@u*Muz_PG;Mkw&b#LNsziXpm+00>?tC!+s&7 zCgqU%8Vlk|I3kE*tIXn9tHK7_oy0qK$r+|{Z!3_jMq7R}Gi-EOZ6UoK$!zR4SO<*3 zLQjpM$HmYCWdO|INb&!_2WYJMH|&H)pwM9Se|iX54YBe#8atGeEJhDdI3CuK+F?v@ z^>kErbE|8<#&bzRKEM_sPmHa8Ge!_Vy2}_@$Pa+|=`-RylnxlmF9*P9lR76oE+LSu zBay{q_UnAwd7(}@gL6cqi>#hWYv|ks*o~2Ojs73JMBxcv3ue=-7niR@q5`N zB~9WTEoTQ4+H!x76=mo1x}Mu2sA$ly2d|=iP3$ke?SJmI-&w28Z-+G7+gxY^_wP;E z6}H)eFYB5Zs;66?iCRuz{a>GN>uj3%Le0S7h@BHh8=GQs^VIZDP;yqfk@{{w3HTcR(Rn} zO-!f+eFJAlS6l8Wm(B0=mhms!O&4p#M?^>_wYc|ubKkniV@PV5JqP(EE)!zRQ9Lc`#f2GrXpEeVI@e{FIek};*pYT&P40TskDCbJ z1*uwf%E|M0BqO=0%kPPjiK6t=_3AvS5DUEpP~0mDx};iBUWFUR9Or zfl0xf@A;6_`7WGvS;zvso5!{e>Gw%TWnmE-K8v+70?S#O>05mXm6`0d*?nwX7%8(A zN|xJg#dwCa@ze3op1L=-DXj9)=`KA^PIpmu=Q`D=g)jrA>9{UQ0 zT|?I3Fa*f<_xITx*F?Gp4)*m+3@OuORd02L+FyPfGHma?KsW>~XTLr>%pN|!Z{n}> z*wB+A6P(U$7yq>#KclaE3;k-Z|+{8n^!?v26C{V)G;i~ zqH2K4G{jPxku_33f#nB13~XI4U#)-smOo2aDfWu|a#ve(HuQi5|6M?x;>M~C-OI32d{#Z7yZfF)`O}~srD?{65Ghaso zsl9{GzQN2`^+^y=DQhKPHf|1Gi>Xm$nnh2Uh!UL5pZfhS>&W-jcDUEcI0~~FZ_E?y zVOSmeKH+lpqJqonZD&hPH$A-NXx%Bb+%y*b+{V@SmLp9PeuB!Df;ZMYgREFl{MBDe z6YrbVsD4^~NR&cT){}E|s7}sxx6@k&cBXMcztrn+bg2{GoZieTPnI%&7tj{++3RwA zqV*HQGCA^Hb?s0e3(TGiGLu6py7Srm5cC+3h9tEQKxy{R=aZad|~ zHlJ(2qC*@18M`+h`8N?{=xXR_9L}0l2Om0ea^&{Ba{G3nxQ*t@BT{fV8n-D$XeBjG zkz@vyt`xzYgjf?O>Uy$tXw+W73!hmqdzQ)^TG|eqJZMeof>69M|Unlg&nbt!X zwqk(1;_u8KeTh|UJ$WskSq=+cA}}pSxxq#Zq@lkd=^dg;PdYmPpq@ojcNT)G$88j#oyH!Is-%%sV8f18!_0@FkkG#3U*FqX zR5Uzf<4M^8JEno`7G`Z@gIv6L`e%yCvj3)tcY7z_qpfp%2p9~c8=Wq-C91hqIY{?y zIrL&1XM`#IQ)jOSdU&+8r@6o4Q)=TMIP7g}s0rO{Yt+268#IRsouoL zpZJVhrl1?JlFH*0M-FTs;axV&=^jOnUpb(y$3d&tNEPr6+`-Trt?!pUkhuC$&G*+w z@zz=P&1L1~r-=QCP1E{N;hI`4QtJ^!H|@p- zX~C#M;hh{_;hJ)a6GZMvZ)&|hoaN5jcE35&xq+Pv!%5cJP^u$E&;$xoc2yYs`RxM~ z-tEV(kvXnoTs`e+InRYhdfcTL5lnwO@W|khHAenZyJ6D?2N1#npjFDUlew!cjv=e4 zhomt-`D`E5g!^$8JZyu5+1oRdBa&B~bTkzM0jN57Je;l>R8$;e#D4blTrr%{EjHSB zo*U7dW}(8bv4Z%>3Ak%1tfqOg@ib5oT|*G7nx4UfUCd($2uL$T3N||@K^6uoSTnk= zzT8kLB1nZr3Ai0f`Jd7x{|u%_Ym@rnjT+V2eNEB7)ohxKyS=x$b%%Ku)yz#2^M{h# z%ZDiR?H;V&Cxdlk^}E(-r+gz_zZFHzweL+tBYJs*$`HL- zzDyviX$@H*dBo`Lw`1gQwhn31)A8t;7JBdf8mHvPUe2C^qz$-tyTk7CI~Mg1_g6V775?~ zJjL8wt5H<_;e{_(r?E^ko^HydiKv=g|5Vk;NeJVy8D0xcEkj+&wgb*jnP-(Jt?mr# zfs;+AidWdoHvww(8VZ)}TWF`j3L)9^x5%2?bfvv7Ev>r_t##9O_+g?5b|S{D(ZAZG z3v9jIcT3oxB+)%uW;qSC?n1tP{p9$IHPPR_F)nHh|H=kQy#6va5G88%+MM3oHTv`Q z(nVz+`ti-~is|ok<|PAjIo&GZFVbIembx&28*D9tD(ud^wf#n?W$~N(Lc8m@8gCZ! zd!_3g8_Tm7fej4F_z`?hoBJ!g=JYAvasJA6J^m9zd~HeYnz-&c9kREAj3D>4oM!p9 z5m>l2+#}ds^eAXirQOvVMHnD;ZjCKM%-`&|9#msBzEl-Nv-JhC;&2*)#){ zQ@r?+9MFnYyL6U+J}NF6Bo)ReBWnZC(UR-(VwFEGQP^Q7O2a}C)NCHpQl zmxG4K)CbL(w=L?#*=Nu$9MPlvLhM1c~;{Ts-@aaZ><49}SA~qnQ3V+u%gm=zUxM1I;8FkTSH24NqAH-&t)rD$^T9O#IT+)x9g%A4ko* z0Rsq_K^pt9u7n`$|4Q)wgZAv%`sj*Vnpn;O8+my-go(ikmAbv~D)6je) zBq1&BG6e@%TUSTR?)F+hCl!*fvzy;gMX0nyTU(u`QTdlktv=gD8&Il7+d-}OM1&8B&)b?fgU)`QT=K|U z-?GK}Q%n#DBtHGRYnp5}rDxPIQ~wdfj9*(7zQvF+NH^;Ks2Oxsf<@zgy5v&C=Sn=S zUCa$MO}1A!Z51*y5?m<+* zGv#e@bR`gS!@=YB_f$0t90t+AXD?Atkb_>yVOeJT>{Xt7s9tDlIVGX&wT1cc%aikx z#(m+uk18a1)ZlI7DFl@%%dL@{GmaU3)~o1esqOU@==o0=&Lk5$gvUugD43WX?mO!K zVx2GOTiTVcY5r0J!D-xS!9$Nw?tQ_+Dq7+QgLwPVTFh?hZD)NIs2e3&@I;unNm0+| zc|ta2KiRA4O6WnnJ~>%06ARo0$&A)w2#&e{XF9{2= zvP{*MNTBTNP4^!09ef>?6+L5b7T66&!pJZjj5K;8!)o%|e@DvFT9!`#AygBx^Nv&X zdG%)!(VATZcKC;8*+)Br$7h;9j(^sSw^f^>qq!xW{{Z$5d|igFwN&7^9j+H?JGb?C zeMsw`szwj;*0+R$Ty}U@ZKSS>T(2XLUCoUYmVQQBAgXS* zcFc3t*K{`qdCkNWN6P8w)6SyJ=dB*iU>~Bub-kM3+UMt#zA{izNk~O}po4*dQF^|g z3b?J!JDvGnMP`u)b@=-U$6&E(bIGx(f^xNdd3+#p&+p$d6^1{)mLESiW0(!_585sC z5ZW8Y-UJ`=y0%Z}4U8Y-E`k}-VqahMr5I1+e!6%w@mM)gHqjr^BPqYs;hlXrA^Fu})7Cb*9Sn#@ND?;eX)x{_Aq zOlQH#0tgV-euBx72kh>zzNO0?o{w&q^-L+aEXua;j`X?u)*q|acb7Hw;0KeLD-b$8 zFT2q7W~s5b7O`!n`a9;=mHHp#X;Occhcf;$#@?tXDDOLM*TsmbL>lSOY`==m*5XtZ zolIR=V6!f`BHHwhat|YU>1T4suS)mlBH%jzi%o>u> z`1o+>_w;HnWbI1qiov4S_DtBBpdjd4FLtEsl7fX{S7mp=1w=0P?uQ`*ENpE?huVm; z(9;jtU><4b7fl9zPUqZVPNt3~$l|n3GCnADCyR`=fRllAYBfh^lHiTL7`tW)GrvgB z)=i@aMuPXH4WcGDXRa4B96#e7NOfIdz#|8^u{v)-Pfm2xR+tzaq3rV~TJM}a>-f7B z;KDEZ*$N>iF&nLqe~#s4(!2dFam(XJBJj(vh)l&j^8NCLp!Xe%3cy>HTv>quF#ur2 z&e>au8r1A|%+Wkj+7VqtHunRJ6?!__#4aoP>pJar=&udw0Fl3jhF&5r$beq?EERAp z;XTpz53$Q0^kDl9Kbk;BBhu6~5jwBYa_Hzq05!|mqQNy}4c@oV&uWLtxqn;x!c&f( zKzHvF(9o@#T$Ya6%@J=)AYYM?gE+-Px|pJ3|G7SHiQM|~_fxLwq@uM~VFU~iQiIL0XITUDc6A{1)Fyf5fKT5+zv9( zz0iYFO%x%Wbrqb0iCg#*NB-U8Hx7?8 zX{g1TF?C=U&jbI_t&}iunn}oIw*Hr%(p=&n%Q9w zLxUwd60b$3xqi1~?v{D>&|O1zcN&LI+$LP2WIrDCxw$r2zbebnFw5o0W4}BWk5s?| zemWVdTijOL1#|EAtS1Aspc0Fd>;^JGmk=WQgECqWzgvoMa6;~n;E9L5`<1jw877Rkb>?tdTBal z4y`}_%?XHSF`R6OZQ%EtA*;*$w`M-O)Fe)&90#fzx2EF7ird|Y(K(23i^x)#TB8l> zxDU#h8~n+T1AbL(rAq$H$tgn=wbUmt^kn;l7DPOQ?lu6eT7Fc%HB}-OsK`u6_PuD; zBc-Hfz>A4UeZE52{_?0BImOJ&GhnP$62Q+?(7 zrSHOq{J{$NkCC^mVUdCQr*=b`s_mhpF~9HZZdb7<75k*eg-pi0%?RR=cR<~B1iDM; zUR`!FxG+R@V-s7+t?Ry|wR41DGt<#}7}ft2J+sgv$eEeJXLwLwL1m8w|Ka7@-PhbC zO|af5|BB5LB>YwkmQ3}h|7$MBV6JR@p3QWD(SzP+)Ighk2h<=VUOMDDFJ5IK5XS=f z=(&vut2N01b4j;b)6gUMQn!UG`gC&VVmRfGl2`$}Y*8`7@r{qrevA2&d*_8Q)@-A7 zeUrRDbkozzn)$ToWaV2lT?|X=#q;MdQqFepYK4Kyq8C5CzTWBF&mO<6l>HAUCHYJF z7tM4UWA6vmH+Y@YpW&2&K?f6OE3Mwcy+XBpd;nGJe8F{P_;>W3VIeRG5JAqIKRCmy4(fp|g&ffXBx_smEa~=rb+S8{8u0 zl0r9=kt~LAz1C18g@w2&j8pr?$940*48szYKOM=-#Zr%48DlnAiraKPd+XTMZr6#8 z!Y$I|0N8A&qQTBuo9ViSD1w?FU8(Ga+53fqoddLbVzn`sLzgV-xyR=i?d^G^awL6@U^TBYBp}CP}YVZj!RLyBFIrlTeso zBqYdjcK-T$wTYm^XI_%Q>oab?x_PMOAiK(KF;HXQdR*0NH);{*w2C17@+xQfngH54 zihE8sF?guXmSPdQUxACdx(N+j_=%|Zd_rTCKcTzrMg0*L26HBORbB0@MEC z_!r>I4soLus`l;slf^4O^^)bFPTRc2509&R{Gj!W_iRO}b=sxzAq3RV?L|`Vq$!4n zg5TSXy^i}`S%L0ZrNd=g3(v2kOs~!wB_%*${XymP;n(@R+Nn5C#3MAWI@2#t&Kul{ z5!ND+4O+d1^|LgMPl=(>ZMLAlCdMYq!u1wN~KUT+7HT!5FmczV>xeDa%{bdfFS)>#?eM=W%hlew6^rg55XCrjq6PuFuis)VkG5oZNK5CVmxfpuo!Ro0BySHF4D z+s#@3y3u3Xt<{zcg)+NCTq&1qa)lPi)M8X&L3sSEzT;AXtN!bDFTyD6UIc@$w?7e4DR86!lJVZq#C<2lZ1VnPq zL6MwuW+dkzIS+_{h=3q4WKeRJoRf%1&N*ip81gW{!0>I}_tbZ*zB*skJ-5!kd-~5z z_1@jPckd2sJ?mMkt6F)^ueLXH4|$_u_+SBzOpI8u|KP7bK6gqTt%rEAUwE8+ zZ$69%j*A03aJ@&rwYY_g0AY;c=E}#_i&`6xsOD}(Tds&$Lnuklq1HppRJ<3ge9NY( zu%p6d`M-PVs2u{uoph~}n zO%_|Gtm;?36)>E-CW+po7IA;$fBul?%}w>@A1fICo`XZC|&2e(L|W0x>> z>;B1To-D=ndCGLnnzXl<&3MvsBoQIXjBdQ3a~{hLEdOo;(W_Q^wS?k7T}p~T?K_#| z9Tv=#)JW`Cq8z_E5klrKnMBo^6SL_7B}z#XgIo?jCw$emJT9Bh_!>rD!ps)N-f%%9 z;s56K>(>tr)u$YCDzunkb|S`nJ`GMrfzm(E&s0xmsw}R&4PCocNMl-b1a6%N7nJXi z0TU63#MDBY+cps#T3w>~dobAED0f0C3;K=*`ZqW*EH+65V{Q)6?YFvaBE6Tk=WznI zwmxxbnuLJ<(k=(MhG6617@8E`PAfj9t@#N|@f-~=!$!OiFbjhQmSrL`a(D<0G ziEmdnVof*t@5$T}GyG~4yR`gj@&074!GN);GKiDjpk3{b(WiZ67`+#Gtt;PHcgpvqi`Wtr?y->&v_ZBU z$>Jp^jCsL47^5i<$T^+PZEsY%T-(3C2WMjHTB$};kj+HJ#3UUowKSeKU z$t_qo4;?WY)ETwEj5%ANN|h=h_PM`6L&@kmmR92BvuB6Go0s!*<3D{OEfH_KO0`xIldQY*bH`OCXMZYfr}?rxS>0}>7t0tUZGP?jr) zIm|fM9~c`O>)fX9w&^zp#srT04FEf59Xi%6_AI#le8ol%`~aUAbgLhViL-e+Latb- zMpJyWGWid_V%-#ecDAbxV1(q62l6*p2kF3BGv zBrmO%DpB5gm6M#w)&5g#&)968eD+qtF2TdjDM5Y4FACA89lHj9^o5}V?L=l#QBj1M zOU=PI{($lHkQWCJKb>Q%KMB>_QTmFWAbGE&*Gx$cA?jGMTvRla@GQ)+uAO==NRMiY z(&xI`q{CeqUlMsJB1vBY_M}i@x!D)t>pR8CO446`QDE9E_}zmA0u3`(Q``^ra7UaF zGzIa!I$&P(xmNt;NjCVUPoH<^&x@uLYv_ZzPfB${%8niEG|qeDGVXQ@_Er1>(W2d3 z!MhZ@+<94RaUNcAeI!!X7G7;XtxxT9dk~G+1G;mKe21z5I6)*`kDa3;53We1yD1NN#@0NmT4PvcKzIs=l)ub;LUe) zb=!91Dhe*65_+m$mvRgGwWnc^Xcnkg(izSNy6+K{2a^R(pcM9k>r6$jneIt@NfAUY z``=z6_Qv!2(rGC`jysjl9gT;p8)I|15X@9O7J1m%*Z^REKsnpOy_s98Q&AlXj0Kb1Of>Qf=a~jZV$>>_9u2s zofXMwCDo@ZOxXakA>W%Tb z5(f=a{wX!lRm&cHLf6W^c(1w4UPNUGC}5J%yb%yvc+)xFsv`f~-c3OSb`OBDd50zX z-9!erZUrg!rH*jt{a2r&UQ z|DT&s{+Hq7zr&33k2&bStud=SXf{v)5`zw~i@dw;W6p~tzR!`Ukr!og?^XPA0O=E| z7qS|!a1M13+02e#%3>rj=*r5bd1B|Yn*EC9k7sC$O!y-0zbt`e@@VM5#v4dTd8%Y#y#!D}ln}ZA; zz!jDd;3nV6((^4@SKLk?xH9-0u+fF=j>89r&bNeWFjuirC&F;R0c_Q4?mWLXNby7m zRQ48pJ~j-DnBuv7I4eSM^jFs4({QzZu^6%T%^gsqi_atPJAe6D}a;wWLJxyAO+|y}?qiX6>mO#Fx?I}y(uWG#mH~rvu~}R5uiw1y z@B#B_Od7uMh_QM*0Haa}IOOfGbb!YvCfb&t<|`#7`<-szz&m8)yqw(=o!iKj!e>7O z-bx4w={Nfv7KBSP0$vo#W8Y=-eGZq$>z&17odC0C_G2@=kW#(!gc&eIwYsK;V~Wzc zKQUfiGIc`_A?h2th6G4VNKZ-s+V zuGOOH$TpA4#xntnwU@er&viMF)v!8GJ`0TCiEGwU7w-MiR=4vkk?-XjEdu$(8Sz94FV5X5d+{rs)5!4%&0lH&dA zqi!MzT1<7oEA2k;?UZWe?}e5b))++)(H-!Wn@`ez>DW+;O39K4__NlXm1&sgFjc}E zboDS>OiO#%fclW8h^kA9;N__}Pe1Z;TV z6x8;nC&IWn6WwB!e%-h&q$rwDR%iG-T%~Uap+PkV)d--HeG{oTrp2R`>-~Lkxh(Cu z&L=>5=FIrNHG3Rpr@Krs1%xz?Ji4U`Y1C80D^V1}S-nc@&aS0nN8m3^*JOPx{LsvmJ%QoRmR#W%Xd=JDTn zchjFG2XMg#CUYA;zdYK2)s@>z**2b^x@}a$dEw#K!Bh^opAYDL_srKrbD;#Wpl0WK+9^DHb2v<_E;$z@?J5gU3hm!_WU+`J848Jm z3i9(E@Ts+#EHV(-CBz05CL(cd5y%zD2rmYV4qk9^ElIQZ*BO2)0S@(DjwW9Ad(p67z>UC_`Wm%cu_I zk}+m@&O+zaI2=hAycwU>$tWM|i)bqy2*shH`HLU1g37Y8-F{kK9$ickOo~P$W#3&x ztF61u)Ie@?dvSqzOD{1yzhiJShNTPPD-F>E{%zd|z|>WL3s}GjAO|bKs3EpP!==@7 z&U;s-XrFfbKi=0o*QVbbiZ8F2oKyC)X$l;62ti~ILq>P5>}j@+{Cc5;z^GyAiKY_c z-bAjnP2lsDA*?!9|#|4wB?rE8_gzgxhA9wZd8e>*GJCd{HdGjqEU8&XjBoUJmfYH8Fu_%7p$iYh zshwR6jJupWh+gEu+-r6cOmYq*cG+l3?Q6ufpU2+EVx=p-NC+8s@6gc!pO?h&N`OM; z`GHjO0}W!sbK(oF1`2*`OgWd>uBh#@~s=MU9U!$+^rd{z!xZf#nM7H?Eqb z?oGb)2)s?j1pn4;%QeI$Q$5E4bItcF;^Mg5&9FM7tuB&bK8Zff!_KOuV;VDdmu}9O zIV>V+o?^VuO$ephjnapQ%836udH!f-`QbEIEjiH+YtJMCqZn3WODS;Jt;E(t4KZfq z=weKU@b2RjY>cNp+#Say`VoyE^R~C5~YTDu*Pr{;R&>TeGdXu!Upz+nbRIzF(50|ykBRh@q zQJ~cbE31d;yTZML+1eHOSJPWfc)oWuWkLN|C|Lc^fW)$gBh`SdQv%`5;rg2om{b$4 zv1Cs%n`Vjv>mHAV<-Jk0j0jM0N{Vq-6v?Tedo7T~zh%!@m0jBaB~BbiuOlmU#M z=3sI5$5Rm=yEgku#U+xz?AVkdqO(UtpVHfmNQ4L<8UH{M>LcLIr#S(hQo+3qC{v@u zKUvS0MtH1V3q`R}Y}5&AL0!RFGsegbbvpG&otYkk+62ph;EI_O0El+^fOiL>OinY4 zMtCQ2`p%)T7L!GZy5k`~cF9CD#PquGbNarQ>^jlbDhy*OgNbOm7 zuO$DRyOkYWp4PkTMmq|z?{$^YyXkxD#hz83G7|ut#id-OJbtIy&Nb1O*t9f_(|1#f z5;G=?=a=a{Z|a$w+2G2Cnn6@!yBbbhI2FQFW{Imveum|+N`=acRtJo<)WvY>Eayt! zH9V>0oV*Y45M26)hLQk^w1|m3+atcWb+hjW?bY;O=cMucQev`*r4!CYRq@C&aGXk( zESag@R&73C%#_NNy4I=8v`ZCqxBj6VJWR>2MIEY2(3~djg!fM?za}LyaTwRTHL7{q zsN6j|%C~0UEcNB?l@inIWP*F!E96a3s35ceGgxqX)lDNnpGp<0C_HB;MLsqj^VX;xzd%O4a z^B~-Sy<(hsCUbxd+K?gUqh?g+u*;84OV>E8_3UUuom|Ppgj#G=^&qhZFOk>upjOj` zQzC?W`PM7F4~_#oCaAc$c)pWZ9*Q+35nA%*GX<86`>A{W{G_-0b3|S@V)7wNRaMo# zv`~?~-`S_nc=#U$-3!USy=26CVg4w*7V}6hh?PPI0>qA0#JV3M`G(-(J3&!{q>myt zT2W7RSw@qH8=dCdS+(-+i)pY3tk_kJhvQ#25@H)C$%;&ancP z?_w!JfdguLBFN2Qo*cb2h+i6To#eM4pS8a)esV#HCs_RE^MlY~&U;*@%_>UC?0tlj z_GkSV^Ji`)g{2C|c9F_~sRp~KY;O#qUgtxov2sHfLEVr2vKSq}=W3Pka;BHa-EECa zj(y*9ksSHi$pIS^8a|4B&^I`kn9O0^-=D-r6Co|Y{rsO5Q+uk|*?Puu;Q2Gr+W~ur zgVlgTIHw@h3dY$Ft#=Nk4hRJrXN<*o4OX+O7$>enNm~_DDFOP;%xC!4qqA!KoS2kS zHw0gjlVLz)(zPFUBEp@mqM^XhSN0OG+|Lm4V0!sU*#%Tqt~Nk9Ug0XyU5}iYH?4O2 ziAza_E#0UdLwGRyt*zVZQ$%lnD7sW7KvlP(KAyzBkfvgy!4>RH3mVwt|IxlU-}uRV z!C2Hf_xh;Em7o27h}%jkpKZoDHd*uw3x~|km)Z;c#rU>!BA~$KoT|)x&wPsrXV>+b z=*>}A7JCC?(3<2F$!x11U*ukq=s$x%Cn}|1+ei$K_W?)a8>Sm=*8a`ow%)q%N?)#vsQ1)7ST|_|4#0sG}+?S-FW&e$0$NrsX;VB0C2w&)3nn7X5lm zWKJaTFR{j*Wd3b|O2fygb8s4q7$l)W8tpP&Ry;xMJNxTSG+FJ#w^ebC)*}4`3wFve z$znCpfha5klCq@Rec_E6Df7ikqpAD*;+b+d7{tF7)YYNW<;EiDE?4)c6s5y@UI}dG z=~1w+KMa2Wa|er}?2xg^?dMG3EV0{UQaEI=b>#<~=0-wsnVK6KaaV&d1l_s?tn|co z+kaPIf4g#wb-lHLbW*cvhIe~OaPmngd%H>wMiO8Y!pg0;)}Tg|^=-~n$iC}i@c0ja zGV>IeW;Mh`O21O(NDPjbk`p|~GKimAdAL6L*sLf<+^D_2UKc639u^VeslJn*H+R!O zRo_O+C)ig&DrN_KEpwCmp57t`2y9xa#_8G_olDcx1H7`O?-2*RB`8pKk(3!Pr_~jL zXZ)mV-bJE)WQcJKSuTJ1GHR;=LOdu#niwIyMF3{k*;D&sFxcyQ`RT7 z+4Dipp2Lf&Gh>@+)2B#)Q^*UA+I8EW_sT z^o(Oir0kP~AAd%bJLEqo`C5IGx-s?DDf$4Ygl|#bujs>cB+>>l<6l7?C$Mq)Zef$y zeY%kI*Sl%yRAz+|mCIuvVec6IhsKqxCS43o*GVku1`cl>@>b)*miGSg>FrBz=ZOO#&axizq zuvW)hB#6DI&5~V0x!tUGs@AgkO%sC=)s($%_p%ui(@Vj{glq{fdv%T@a3!a|PL|VA zvUe8u>swLRyNy5T%jjF>jzbQrbBE{#amj*QKvSo@mqYZdIzUlQE@Fa0ruH#UT%};0 zT2A4;h((kNWA?my3GUjR3{yhXKH-mrJ55!1BW)lBsUfQtU&}sRI`rs0?UUKrELDfZ zkHrNss4w!F`LFP6k+mZ7pR?qjm`Cm|U!5q*G$21nXq0$hcwwFv7EBEc=h3oa5OZqs zMbz3)%&&>U+<&CzhD~)6t1pwxUMw321$Pv$BD>g1Yw3kOE^HGrt@jnx5ug&~>UNjQ zGgaQaK5ReuTHNBn81@4PSe#4@>SypXZ8>r7f%5m~p{wbn3-;KU^d?CO3G1GoKhnf} z!5v8jZOp(x(*{1nkK;NsX?a2RMFv1$WmGP7;`eNU@g{f7-kh3K%)2M3P&TI!iL2xu zC{h8+x%t9E13bk$j^+fKE<+A98|S;+Js;TQ*qUe$Pp-yL9ae1WJD=U`h}|is6IAyn0DuI_((Ci>P9*YTVq*Ho zo>HOBP+e3E4U?e2lrR5#2tgg$Rg3!%yyz~dpt| zZIfY*E!%Shm=$lVN8+5?;fmSI;#?kUFGj#hET4_+tB^j?S=0A{il`8{oWR04;IxsYY5b|1r$B{Ph=b~0WS&n#@LsmW&Jf5 z#uqK$tuBRA&nGmR%8Mbo2`hk_D^e}g_X8edvOL1&YL_jAR#wC2j!B!tqLt2f0)~`+ zqno*5t8Y}d*Kk3h9ZuTN_x_<@^1uA@C2-rvG|j-%>LrW&Qb^e6{hO+93)(`pr3?)S zvFVd^!7C@`iJC4GV5@k=_*7-6mk_9p_|c;e%7~_ z=o?;_C6c=xJ9}jWM%$3NLM1l)inJ+cb4!nRE7CT9gw0u8QmTrA<{qD!QI{e{fo6^W z_1?xk`}01CxFv%32f5A0%P1cH%4RV2u(ALc}E)cLjVfU%)c*X2Q%?^nE@oOG*@ySFp z@ec%)qlUJPbL9j%ttnYkN-c)QdF`B7D1U-r=T9KiMcX5?Z1?M=inmoQ>U%~LgiAV zKW6DXxwBH9?>#`7ELtCTD8IoKN0zM_kle> z@WMlIUZ2#DQ>yq*9U-_lnzjRj^ZbdjvnEZE8$PatpWXO?z=~N@`>b=RBGgVtpKjA{ zz8Hhw0t*KEjp?};8Cqu~J2f{*x0sv_C{8M{rz67=&$Jz;fTQs(TK-es7SyyeV(P-u;jlKUP=Y8rIm9PaHwtY88|B!1B!kW%H?3LK4&0KDKTwD|(dz_B2RfseuDdaD3xOI)<(#zCj8M#vOP5(55MgE z4um$%VN378m8m)@U#{rL(Oz{V^8>o0TZKYAgPQGyh6k$T$hM!bof`f3vgZD$d`wAM z0y~H8-$5N93~o@77MC)V(*szV5L&~(0?^)4^`FPuL8}p2GU*ECS4sB3=Q-9d*%@)j zH}jU-zRv1k)h_sP3UE}q4n30^6L{{Pbs?jpQ#+9*RioUt@9&hF80#H4veJh1hSt{V zc+-O#=|z(n#*XMzsQ(s>j%pY-x#xF#O@~w4|YwIDZN{m=;MmaVGh* z@>NB#<_4J(K;ZLrNdWMiI9&PhD!SRjPR6MefzPuBat^ZQ~o#^GRcoWK10Sn(t0fm`NqrdZ!x&GMcq{2~fUjY>7m?_ftmd12n#ng1@54t?_MM68q}AYnAL@?f%#-@+&qKrw(&^ zHNV(M>X=-Bfr0sURRc>Bh(fyMM&mUCzU z#>S|Ov<$IcDT+)w2NTW!*a3ZT&a|!>hNM6wMiQ*_W(OcdbEq?f)JZ=Y9y9O<34qy7G2> zO|)cE`MqMknF#@eMzj_R1XVC9<&Zf;xD+evHi0uJhRosD+<4HHvB*J5~RuJVq#0*KB1-M+?y`<@$G;< zfRs!|8+xIE$Jh>MRG9?){w=>7ydPOvUO$KuK1bO%_-ir%kJu{pmiJp)pjkqa3;^JU zOIBG*l_GM3q>`%#@6X%49allmfIdb0gsf!6?z=~PmqP^~_c%nZafxiSlA#Ar_Hu{s z1$yq!b|nBH-OK^*ja2LQ4SN7YWF3Lb;e@n}+NT}#LQ7%3wchaUDKA&le$*+i?VyqJ z{vP>~9ivyNw2t`!27lVJXhy6_?dnYvz-ed(XgE#$^9_T)3IN$wUk+8$6a?4;o#(ur z(VcJ?39}`i+LJcdw)3m0AnzN8jGGMIEG0KS-5cc4k zOqz<@p1Ws0)l=&Sf4|}W1>tl(@<=KwvNNoCujbh1TaMk2=s6?7$`!`A zB|)Q?GfH2+=MOeP)o_LZ9#4O9_klW(uR1hc_z{L^8TvxrxvJ!25qA?nZPu!ER`n*s z81-LYr;d}o_m5=ACwQ&q@duvsv%hh1)r-Nc0&!x1do(je z%O|5HuD4S8lfs&JMhq{2mH*=PMaw#%U*qmqO}f=-v}c2v(gg&MM_&AW%(reFQ! zr3?lAHSSljV=!!*D+up!=ZOVGxv_S+!J}_VODRmv3Lkz!qX_KB$kbs~ z$3&>XyP|N9JRG=b?uWE{jiwQ!b&ARLe`d$$23cARmNyAH8I6R9dHWMOYvmwX2wa}J zIqS3=;lam=0k`U>8o-!!h#+E=M=?K75rgqcKGQqcr4|;tB4?%L81g3##P-ZVL=a@7 z?z3P3s~Bz;O&q7Y5lnXJ)b{Kl9pGIec+*xAfYHq$gJsbXdwKoNG_F)rY|MU18ge|i zd5{568fLKG8W=n+H7^`mAqclo8^I|E&|N)Hpq>d0 zz@j$M!bIjR4$1{QWodUWTh_lt(w_T^B^Fb2ZOow5xuBF=WwxV{jIiK704AKm9lZ!s z!`jn6>Deb~yXT|9@Ey?dbK+N%u%iQiz50WV@W5$@&W;A^P$ z!V3mbl{>wt;QFX+nz4wPxPj8^eFcEVem0nuUtT^+)M@7Fn%vQsdLE&&&&(I>r#64q zq)nw^Da+K~+Xo51ih_k?wk@7ehadKY}aMT+(TI&wlNmoqeJ?UfdK%cLC@11_U$rAglumZ>6W%@3cK48w^6^sm_O?7`UFnT7fFNzwGf#5qO>S{Ma;hKM zo&--n7c-G>g8~w|-%$@)^XrWOuFAx`+`iy!-Txw?jkd1u%Dd$h3RYdwY9Zu-id#OJLK%0UVt--_NlCjQy zR+18syM5r=-oM(>7L!#DwW%I+p1%X|-7ZoP=UZn}kZ&-MS&J4IiZ{Cc>K{Uzq=$3~ zd8vXWz@-C|oIyJ-(m_Rmj$nrgGayHjW3k=J1O=@R)YF?Vdp==vmsdKy5-uf=p}}ea z*0L7^a73PQsV%{T;}Lgv$sn$Sw(M}y@u?JRxhCwDfxLle;(HPh{Y|0! zn}<5pTmkm_cbS*t?fjlz*2Wlu*DWTLa^mrVxFFCEY=Lh1j?`X_L{VjP&8!9BOWOhLqoyU?l5kRUTEiL_JS&ZR)nN+q_Kc3e9({~FQ z*}Re$?>{l9Vza*I$H_x32PnU$mpB~8XkA1ZaktF5pP)`siEj4iL~7u3sh22gYwIz9 z?|7F&RF4S&a^+omYl$6l_X}jkJi3dSbC(3={t27|{F{A>K@a=@>3?qgpY8!Ds(0ys z1_gG=T|fM9%$ZO#U$q%wBS-mCNO968FR*h0sWTexQ=1Q+r(2)dz$^T-Dbj9E0+|9eO0t;h73zv#TM{6KsTCkv)@O&(H4K6?G?-*$lXIl9K0 zVe1Lz(095ZgW0hHvH2Jimj5Vg&qf0$lNVdx56vI|xw_XH#*z&P{6|5PgU`8j9<|`= zfRKIMkOGH8arx*~%6|)jL^#LBj9?bJYmm)s+z?r=C53la)c;;{YYB_hLynK=_uSG^ z2Y$|_dAxSF*8ypjl{sB()y}f=T*^chWH3LrP6NlgB8M;y99v!uhnEPgy(*Wg$|U@^ z0e?i|_AG4luMW{`D>xy{XA2v4nrE!&*z65?^pB@(*L=_3wzy`E9n{?01^Dei3du0% z75lm*ajAd%w-U2+t+{cZywM@mFty|MY6q*M7>FiWI<(0-PXhTk{2z~?$fbdIOQ8m& z@If7JwH0SHCgy!zQ_bj&g~^k>VeHU<>II2xP{^lW$U~0hF>(|i9_Eg$It&n%*Szl} z13$w4_d{-m1bFc*ptx?SKXH9GqVczJa|*(+;vuLb&vg~gCax2fy_6MQm(rm}&l9`P~`6A`E4NZ>p=S2S;q?b)yy+8O6MvW+Div z>b&;IXn>g6K-ftg;LJ!ZZSC@GK3-m{E0`8!E~}{na9z|oTn^Hyu^B2wLu>@I4afH$ zs46WNt#PdDh&C5#_Zqf%m#?p1y<}xo1On!mjdcVE2cIC3`fuOnyblW_eexs^2=PbC zZlD3M;dKH2r*6IyDd`K1kV3Y9-t&v8O@uBU2}scA+QQ7GX$FW5Z&Ym+RiK_-0AFZe z6A>{4q~eE>QW|9jJUu;aMJ2kWW{BH&)*!nJkzoE8!C{gPQ!BglZX;O|u&Gig;48VV zJ@X8R;G?NI=CIgUCF=P%2M8L*BmB?z?VNJ3#_TkY1&iCx1lZXem4iFX08Z@`z_V)F zybTe;4$*heXpN9-roX?~;#28=zW)ti%U|u+;Smr_IX5g-EVyK(sd|O z1=Kix9Bt&?tZ$Qg0EFu054^ZH4^Zf#BI&Ihpw>a`&|D)Tjp8B(HJY9E&z)J4G}va| zGp0Vf%K?Yl=<7?0#(!#BRVq~h`TjnRek!(@4)`hrp)YsR`0W{>(>SdHpw=?;V@gg# z%2tmZH3CY04Zsnurbi&)plL_9!NnB!-(8)1I1MzqQ)=|9x7YF4$46-bdjXuq_gBO-wB8DJXS16Hohqp*>B7SK^Yg7=@JUQ0emKt*vnbKOcftDNh4iw5d{m2-RXO7ZDVEK(!s~aM@qcvDpB!r zigl|oBGj|u>$!_$Nq37HtaYPqa7BE@8hI19A@Hk}2`~D-Ueu>>o$s$P8e%J*O9@}B zo%!um4Q=9_QyjPouNDPjyzH>4Bid|vQEfC(AIW4`RR74=Zp$|>bj@<8PSflsC5 zs@6I`-aN$Ga?LBWv76uusPozihA+Dr*s5n}YhB}H`h3n`{JnDg?WMX-5ySUxYS(Q> z-3lWfQ~j1iM8Pt&CtJKw9h_EyjtOS00EykQ<l2u#wdLs^& zqb3N3>-A0Ir4)>|S> zn#$4E4VMq!o^R(~(Wx|S>^=^)C_i_VDDXJ$>mU4M^~EH-a~0G(i{}xz%2r(9vy^ip zbn#oLlKG5k;V>XmETD^{LBGyiL_)NvTtJ2#;<`P%m3FmevDe)$#^0XXOnb1B7VD#B zq||)nO`SU-PqKI_N=Ey=aJg~LKX9$`<_tlp>hIBx*h&^lG2Aj;-p`{P>TlUkQN-(m z`Robr4NzSa>`^7w{al-UAFoDZ3;W2F#$%I;KoeZ>`ADw3ai%NZSUSuNDwfgK)<*QP z&^iA6fcKg6x*P|kSJdBVJoV#OkHxb&0!)AxkOSEG3`p})XS?v48Z{z1$ufCbKLf6g z>uO->9R@WiF|Qg627R@OyVbRgWom|Zf8#)%n0z{S6?3VpTt+LRG0-oyL@Ql($EByz zO>#SPKnu%0d@h6s!fU=*O|xknX<5l#A%B=p&Bp_uqO7NFN>g>MFk-7F&W5SVT(5?z zJzY(b>yFavT<~unk_fw?y((e#m4i8#RPxBo=`Km+3CY`J%mM6j^Q_ZFQZ$8)*yrrRGVP`kS<{oA$W(@!ix$KO zh@?w*!qW6$o2WCJHR>q~QIBKKKF0^hh4J>l8%$~awl8@F4rhPIu3)8H6o!pgJL5?DBfc=qz9`Z9#LCBS%1LanA2(R3h z8T{M;SR5SQ#1&5;4$-UW4p zHTBx#BPiq9lI2ox*T!YNS#Je9`O7x(=0{GBINZBA0ylt^PQ^)Gm04wei44 zW@W_eCcaHV{MUY_a0$|LZ^p)NYH2CGL?Ja$(no5Ld96kgt?MCa+$D?nBD+#nmuBdV zmNrqIatX?;6MqN<9v$R_8M&s2ifig;X4$_Ta*7PPxIAWh017yc(k}*h?+&v+%uP5N zx5L&#bxZgU$hv4v`_LGrg%MJk%JozdCZhU|ruWF20o2Ln z7X)eq!VZ)hH^j1qQ=e`uTk8?~q9$GDp>EF?dW*I4KapamDYX>5uWnFQR-Rbzi6*6^ z%igQFj9)4|I|*d# z^5s4@sE^Zba<>k;+|mb*ar^v$jQ#Hv(hqsCG~epyQPDhHBXu+7Z`tlMp^4i@lqO|g z*W5sD?%a8xXd`GbBFI>7Xw7{8gDcNK9coeBNGkAzEj$>s`Ed&0yGTAgj^FFoV>3WE zG3(mH>KsaMa7$X%vyof%vUJrfWE~M9#WwR<^3t1HjgvwfT%PVA`%(VegA|TZor|4M zY`B#@+Jk+b=`IB>rfx(5E2RNPX8V{79jv}oJ#uW?ud_jwwqC=vQLRRT>5U43C)+18H zt9KHYQAi=tA2--U8tFWIBDO)-(d|Kycw?85K{5~9)%!>uBd~3S5@NU;ywwP?c<@2Y>+^Nb_aqjE55vD!`t_gp?~ROQ4`Azm!i$*{8}f&( z@|~XPAjC*lZL^0vep^kxpK|R{lS0iQFWnLyS zE7f)Aek}r2HAH|FnG47-Hf7W z_jbZpt@3qF5#3qqfloncycwyGrmp27c>(*sfufip#wlFMS!I_6!I?u@J0Wb?k=U?# zBPK6Mb~0tvzTeVhdxCN-l{WqBu=Ze`px%{ADr3`9Kra33^g0u8 z+=28CH4(f{1th;>_3UN;?Nr;zR=;Q`8b$`;H~~htw>O0XcDo8OhR7J_E8BzRt&)@D zatG6btPRO?EkLoD6IBDEstLSXe-11XYBCY6CEbxkd>0v3?W$npDJREm@YmjveCgw- zQ!P!O`gJ)RZba3sK4M~GZSL#{tJ7VNuVnbx$Rz`Fpe$d-hAVev+jYkEwBGNmb&!38 zPVz=qy?y>wXcq>jm`neqP7v?kdzG`NBdu#?%bS#>9O)}Y!;hand2tK+f7*NNx2D@S zes~}yAt(aU#;x2UDJhM`EiEuQRYr$&j}TFiP^43k+F(PvL!~=L!$7)ovf)|dKT#k?uxX>;T)}>4D;N3L*3-RT}_{gnLU#)O+Vu1>Ywn5 ze6|%E|HaY&^X9Ub;N^wy`ybOMDQE2GTm=ZEB$+&Nd4uFtY*u~gm_U+qOoanGzwxnl zMfB_7rlaJefdQ2K>cG16I3ik=LEpxnhv>jKRl5T$r`OSqrrNp2Q+I@%X6k4g;O*VK zhT^WVN{`tY@#O(K&m#@TpYU&^Ehl%j`@YsU!zbRX)=W!Qy)6kYe!RUfo-Ak(7Q$D4W`f*a}ifC;yE-ic1Mrjh{!m_51rzHD2c> zEIe}1FG=CifpA#_H*(9JKs7J{lM}svMM&KO1fCx(hbD&8#>NH=y~{|JaDtHs8I1c` zy$TOayt(twD7jCSvJ&|znkkRD@KJG6)o{-lnRfCPtfQYnL1wr-4aB zDoeyIks80^wU|DCtZiqLC!HqgrQ2p)7M9AYl-u+{8d{+D+|$DjQT%~{;BA);q8XuuADl(3L1Dd?aF`Z=Xo_y`fT#xHY$5)EAaYh& zb3x~l)cH&Yi7D6B54!kUuP6~@#+!$evKzsjeYwYN-_o{jy<%2=l4BHjP*h1D$2;>bV$xY**WI-VmbUL7C zyeKF?vFC0h3;Jc$x~h;+4KAAp_T0QhSYo}`W;)G~%@|-uYUwftzrx`8e_9H(P8!uY z)naP(I=>=x^aEwOd5TYoxMr5*>o~I|MHW7G6dx%$c_ehXgObEV~Y^YAezU36&4Rr>u(1T&xzA2#-EO+N#Q|mJr?VC4} zm2Ybq)Yb z&*CW{#lofXvu&5G3P5-{L6{_wB7^KyQb9gv_omC*^-yhqsw>c307TNpS4inSlJdfM zvGz#0dJOz4BfTmG4g=5O_F*!SN~>DHL#ST6RcfT=M2^MKmKLTfx<$)77z38t@!FEMR;| ztU*j|rc-xzcB&c2<#gkCM~zw@6XW=m6>AD^8D1et1p;Bqzd+dc3I)aP9*hUJi*8Iw zfTT>)P|;@YlN`T`>^jW10wLjCdG!W8736sSsM3vOs$=8o7$_MNvl-M^0abH{-I-m` z5H$wt@KCbT$@wRSFx}j8CG${WPPevUmQ=8Yz<9Qv)Dv07n=*)16N!90UCWe*?~l;i z(8hV3?jq2KG=KSF>!;*?LRq!!5K*wIUG(x1v=AEHOSyCLI})zIzg4vAzkNrfv~0Eu zd3D(s2Cr(UnAECyJvZqj-Tx2eQ`6(VD^CzG(x}I%YiI|2-C0_Mw!DE zAWhq(tE669K0Y-*M_V~SgGS?!npn+6_ZB?sj5t+8H?I{1Qp1DhnnXN-&?Y&(zls2Av8@6&(|$HhJudtBL&)dU%~vCL;r~wUnYULQQJU~?uXlZ5<-)Vfy*Yo zuV2)Qppi>zr)p-6`>})CB6Vx{3gFi_>8&fYysF@K0yiKFT7G}R^oVn(A_Q9tUbm&B zA=vDJ8^~!stHoO*U)^dwNTUHJm5}7`CVKx28e%t!%4QXT83x%I8nT5D`}kajnKjKt zWN61qBYYQ6_)lR)T#Xj_%u)dqkOeuiz#V0xP!vIdbx~2`H%&c9G=7sS3@re311 z9PwVz+q8%qv3WR}&Fj0XlsTzYM zYEwn(xLao0E}J!|b@ArTw{0^w+h_%|*h=T`Q|A>v7xAx0(xr-{+sA~+!^moI;(Z(% zI`|G(H#x}I7ywIb7tqttYDXKiOk^vrKMFUOFCI*Gp~a& zFBSDtO;Mbf?}tky`p*a*>fFJpaEPY-qbT-mnZh%aL8=EJgl+5PiJ1LPnRRh!b3OweJZ#Lrl{Rc_qLc;xr6)M1-{G`Q)h1 zgSEp+PK!P7n|>nz)YU*{s?KKIJ0Ld-p%buJ7&z{;XfPM%s% zRTD?kuul&G62%g?uvKUeXT86A7j=QRE)(g*+kTe7qT6F9dYP&?SK9;^=OV$4PEIG^kR zs~vTjRHt4OeX$QNncoVV^Om9gDuss@6WBXBM+ z@he&H3;I@@LuMn;Vs0cG-Q83hfXFhebj*o+pa(mX{PFGO2v<;Bx=FsT{dF=J%+l1D zO$Lz$6&n*!3Hf#VvCJud&HV+TdycupZ1i+mN`3#{d20h;EVL6&bs1LfH}=lFA`c>_ z(yjFAzaF~c?*!C!)$%HS3!-*$9pIkrd-tAlef1kB?zB5kC)edFT3TMac&#X}p+r|U z^-+8~xvOv~<&WB<5{ek#9Y@OQp8#mV{iK<`4!AwgM+yNLAYr36VQ5HO1?zW^aE#E< z%nTVpZiN)E*-sQPC9n6~6U=w^3dpFJU-H+EgfZ#V;v9<-OIuvelhX@+ z)oR%OS>G>Qs-edPM4hcz^{9%7P~gwcIk`6J5)I zpW^oW5l6(>Kw}3kX?n(+g23Qnj62xmNfKIL&R%?CSzlIYb8i%d6$-oTo`RX_go__8 z-p1#BUNqF=@@5>-;B&EJx}0!s4z~OlA(5!ZMZ0fKCqLbC6-a2iR^p_S!K!;{)|Wc| z!^?}0^ftc+r%&y7IMSrP%tDu~8e-OFY~QVw6%oM3il+&^9CEJdo(u(F2Z}wlO@y;{Qa5oatF>_3E=*cY& z=~6V$+v_>-7~ssFTl0yBWfsw>r*xOPyEiculH{ zQMEt5cAA>~PJY1xBK76dTAz74A~%yP?ozOs&e$^pCabZsz+?ZUE#ClaLoFAeE#2}$eKeHy%Eq;* z=`xSf=?Ol%kD0I<6xF6(Hv8qMeZn3-B&={{c3Q+G=j+$&?%RampTF)L45|ngfZ>tj zQp7D-$(3K3?4}nT>SXt4$pEDB1=7s=J>4LkGH;gg_TQ3wx*Xk4!#$ld%9Wn^ZfKeH z*wF)kXUOxt^QDW^eSlcGKZ)H#U`n!-b^f*vEuYx}`Ka6Bn=f5fvvb>k=NZUd^eyzT zq_Tri>3}55eG;l$ZTk$G=|!7H-c(^Ir`ctjL3^qg(P*>{U51f1cKl*qYrBj*7+#lH zpI}$v6-tawI$rJ$4;%2el5BmcWTIVvgOjxCMqhV3=F6Af0;TA!@Q)u~f-2Ruk)nj6 z`KO^z^%ZCBBGa`qp8XQF>7obs)Fnc?oj<1KB)*Cw^?v2QhNp@91kKRc8kII_80q-6 zOY0-(yr+qW^S`|uO^t~xLTlGwiK{>DnfY~YWYlG_tcH(_SfS&V1QDr4ha=Ji2BQ+M zDMBE`d98Xl$RM@eZkk5Z1oU$@!cWhM>cbelw3P8n-XI6lDYFmAxtC{PR3gOAaPjpr z3H_FgB7|xIB0frTkn!qPn$&cbWmk!rn53EhCn(>WKJ8KmDBo`(Xh_#5+iWE(+-Lz! zL;3d+zGq@*D__yQE~HLhzs3}X#*SLI|6)AQFP9JnluQ{wIngqszP{!CPtJ{82kM67 zna&Djw`)e&bLAwWM>cjJd`(YQY=aatmF7I3I;Jd)Z?rBOP0JX+81q|IJ`UTc0^vuG-8n&L$pZt8L|@0vNf<4!?yQNi|%2BI1qi z4ZHkw4cj7{`mQnRB<2rb?}z)j(?=N5WqHngkXa`n3WGP11%c!gF!5!6CwunXJaGNO z)=J-J0Bp3{%&}t0g|v(sE$1J!kNDujf~3+m*j4P*a09h9VgpTr+%G?uoZMJ36|mZ=~?jWIDXnWptVYrWFjWsjRT!moTBUfvATR|)BPXi?kV-Z`vi zWQFW*7iX*8GRk+Z5=|wz<=`HPL$C(=v zfCH7&$ER|wOln;fwxIRmHV;jox@qf5MZWQQK~cIaem3ZHV(B^`c86+yp5EL`dy z6NXaM0xAKDpn%j08Kuj}N-5<1uw!Z!#lyQ5FKm0R=`cNAe;<5B;@!4k3HRi4 z0s6UGs<)&c2PJ`2vybhrgRui>?pS#?y%3 zvZ2srdeCRFwk5l|{NBNy@B<_ld&qcm^DaEe-u5mVG=uY8l)CU;|pEsP=|siS;qApiE7ziQ}g z!JYV(;W;wdQ!OL3bR($A*6#|51Q@8z?l7I z3fM#vo+vA(%d7yRBJyitO?H-+ut$dXI7t>DqzVhRb8}aHR&x?`@}gX!L)Wx=3)+5G zioM;@*ir{4rU=F%@2o4W%iX`0;bA?UmDcH2_abPSKfPuK zp?0w&C>s@WzQh3D@x2~73k%%q874}JH}x; zDPg@37YNBsm$=N#oAtY`n$uqMk?NdnWN<+~uc3)~!C$cEjHKNoSS*WTKfCEN6; zA(yTj{XJ+4t6q-lHVs}~P3m+jqupO0c1zRv=Ld}SZiWWb)}>~U0}gxqblxTeKXPdesk2( z)a9sKu5lOo3W1F{NlD*7sbYsgQ@{N#;|M?D>v`x=>z{V6s|g-6hhA72g(j;lTFnD9n#Z)|M1p!aH0ydDGgKO-;=F+?<7{MJ}*KV?0`_NKz zj*axMFxy@oP?ac0{*K+n3I(AJu2fsiUzNI49hK3Tkvy&aB+?O``w`tY)Tcf2qy8gh z(((r7X+;@|22#Za5}h7si!5-C`J+EQ?e(U9Vf!uyx!}`r@}F`X+gl_4(F_d#+GAC& zOK(a$rnb1yN6|OXy67u&Z8mXntP5se*6>oinbmLhQvSTFx|dtNt>^=%@-A`{ShU%< z?KXi*n6yvuc*YM9Nfy?#`(MkLLn|-kuns9W!eu2e>(Vj?qsb)oHYcW1EsT9iGAtzR z9m_s75Rb1CPNukxacuxgxvfd^2&TSlZ22W-F{C<)d+CT+qd5YMqw@6gDI4;)cYM`G z)77>zprs(`LX7?hSJvb0Cf~Ji;6gc+6JdJo_ZRm3&pdcUM7q1}apRyQny~7-^7G}I z+@7Ny^Fb9!>EBx95b-}6EKTa&pX5u2J;6wH^-%b|FoAl zIDa{EpU;2LQRoccT*SpaWeQ!3e|xsMrSGe`+?%>gI`$Mq%i&W zkz_#~=ZMM@Zp7(yQQ8i$LT2anNog~fuU*RmlvaVoljZo+d%5=vp#F^$Qc6kU$TeT1 zP-dc|c`WbsHL1DWsq5w4R1dS8o?b`y)8rFgK_7?8PK}jh0U`x~p{c0d6c?0i?O(lf z*-b9ccylJb2SeDcIrVDdD>AE#0J>c6rx2MJxZ>kh3Ml6hqdZc^Cis+ODAn5e77AfoDAAM^G}7JOjr z?*WJOEks&<<$SpT)A2+`f;3R@764(YIq(>?nOQ)0U%?u(WK-{#BuT`{(L zL>Mf}0JWN(z$+VflL1o4N^-N#aHh^1ldYtYcXTYB#({2#m>FV8X{+Z;#_-0V+6YIYiIp4rux)! z(u-shb6JzLiencFCL;r(~`&VTNy*cT6Q+?a3Ly z9^yX5=jqK^j@SKtSPk#nNe(oSV)WPjg3e4KaAHnyVh;!f#TrI0EFT27KtSu~Q{p4& zrqUx>Nafo`UX%kOJr;QG8x?>VC+qb~0-PaLCM0Zle^;dY+jV<;S(8?PEc?2j8uB!|T z=KRt?A>1$@;(UmFa4*NCIJoh0iq(X`v7L5q0}*Y0c86NhJ+&tVOkqN&hetwWW zz0kv^D6Mz@_{~upx$s>F2-VE|IVy)vzfG(is9p+vN4}d`k>oUE^xc5_;>+tc3HI+9 zG8|~YKMkk$>E`d-Ng$0eS#C1mIs!RBI#%g|(J}*Zqv3JXX1MS1*$L7;$;Sun%^lom ze@w&`095W!X%(EZCvjab61M2=JlPJo)iSr!=athlA49Bg^UDu#vk^ttuQIj*Fc842 zE@Xku5rB6ACbtW${M@Rr@%imiH4%G^d_WZUW~W$xG0fk%Wca9s#cUXe+gzt5Rn(QM zCCfV_zg!d02cT~Kv^hPIMEkro!`iaUsQooLb?KOi`6o(6ZG75?t`RBf=1*TFir zA60Vb67L5x7Aa1A5-S|tNMLKmG6g>-6};!-h%Zi0dLiU2hL}Z9^`9O!@+}5pFVmy@aB+GTRw(Vlb}G`JzA6_5O&RuDa~>u{2i-i6SBVQ&0Be zyRV@+0R{jhh0NXsU~h8J^&9yC=ch=}bsj8n7bvz*qDS+&Zf? z)tm+}NOM?4u>L!cqYLd2lvD}M4>+9t>fTN|aLxED+t{#DUzuAyKyyrc8rt07n${EK zHLD7Kd~xFb@e`f4bH48b>6FJeFX#0=sL=c?WO19z)mOddTzucfWcCT{lW8uHd0-HR z+n1MnP5XgwDf1XmM-F-eCd@|&1*kgyo)*wOKIHf}^)iK~c_y&)-vM+*R&yU(u(`^n)WyE zp^|#X`kok>=1x7) z{2Fjiz#Aegem&ni>Lai}0=vmTRCQiLT`xBhhEMv*z^{ybLk{m1z)jbAmjY7Z$&M!z z3aQ<>+k9JLwO~sHA~Gm~o48|U-Co9Huynvf)KBSl&-^)b7$zcUZ`Jnj^A}d}=(v1M zOG|!0?qmVVBse!-k04Gfo=e1O4$!91a&jK;+k!ft$?;bT} zA(+?zv2&-HsPZOP?ME64NFeY|f4Dz>_@KExQ;+%n0`&KH6~NV<67cE33M9_<@!{NC zKFJ3+!UfDe{|!ZGE87K3%#BQnb)^xekNsu$b$Kwh2A^r(zOZ#kZpCHf#K}9lpE;aS z9wS|*AC9NnXjPlq6agu7O~n=-a&dx`x1B^>^0|q+8??t1kW#7k+7!SK+FQCcS{6)q zAny_;%eP|Gxz%<~_osd=W&Y7f*LEXN2>>$4@j2uJ@){#!HjC*BDpxIyhVV!GnwWV< z7+WPl8pLnw4{@SEa|5=V!&q^1vWfSf-)|{Q#YG$Q-j4`O&3(>FyW^wk?w5ag^tE86 zcASr;t3&AQ_jhl4QjSxINi82e(~E-XB}1m#duQL&ikO+ijv}ybTN}43GtPiuyKv-B zL$d9~v0C+MNXg|VJalP!=aVw~em6koCYGW%`;p1CZ^M6`ruGnCSLJ>vhmR_geH zB8}0XP)?fhJi39-mz*Ph`KsHrL>t9zd8u`G-{!mEQB{;H#i@LxCNDfvhY;jR74Sei zs%$gcq{wU5;8ziC5r3M@3eR@9fltb5*cM;U860?)Ce;fDH{nj#(W^~CmuRI}ylJP^I=@*%3FU`urCeLO!5j(AGI4%W{9c z0!6n<1qqzA2euJ2%fU!7bBKNp?tVWQ;sVMQYoqV zEX;KUf9@Ds4^MPdP+zF-R4#tBNe-B#1X;mkrPJtUB{nxNeNFW^;Yl}jHm`fv${e9+ z^^@^J@>&b%YEg8ZjccRiHAN^HFDN}LRG_MU@{fLul)FtnQ0WhWs+waVMu?+Hbw(6K zVE2?YkU)6zwc*Y5M~4cdExX`GdZUIFx3|$i_gvt6#NxL0)wAa>>dQZ@iY;J)Vm0+O z4@F7~I}ybaj0AW8GhHNA1TsnX$TVffpnfuX5I7mPipV5?scpZ8k0ALAA=dL#JQNvM zxmwi?B(uTfH23A?(jP3|A;kls#3`tm5`-!NeNBPan_GEN<;0SRHH-=<|2pVAGtAe# zH5sKO!dMKfmj1VXCD}ZKPzrPT+#MA_9xhvB7C$5k)k`-bDXU@uzZ!W3Nrw383f#;kEmx zqA^!28QM>TLkX`2Xq{75cix!bZp4+&VJ%@EV@)sUk+=|v!CmoK00_?{ozebVHfY}k z?(3dfvP;}7b5YmuP;OhEZD-N86cgS7c$}jt*GehR0IjxY?xVFc;|hBNC_?AHo-y{% zBFzepH4U@%BgI(vCTY5M@zYNf8s5g0vXkvamFzb-GHZQBhXOy+Kd87#etTnf1Vtxy z5SGWpeDyJqfH;o11Dz$b$WV+Z#zuy6Sitc0(}iK3Pgz{oB#92%4ox>eIB)nd zV6Uke1ID!EudGaoJRkyTfOyoWlQKa^Q+5vm0LTk+e1maD?#8H=+E!h2_VUXb7mNBw zc@Y7}3wr)XbFVC6#dTAoI{5}a4fpI0y}+Oq$VM-?ZO{io7Tn>;L*=G8)wj`rY<1#@23A&t1xm7*VGd=s6v&ZX*za&+>S=D-&QgCT#-b9Hlx4jpftZVw1hV?}IzK zp+~E3XPgxes_xA0W~U<8Y8@uU>2CC!ff162)p9~-1ozF;!pDzYj=of0W1?Bh>4;uk z_~u2dUKzocg;0J-5H2kR&RNTS0_xHw2OqZxSDL~-)^=Z;&{WBD=udFs*ECd?V(IG| zb}$=HCgCvpkTY4F!Dp8Iu3G?c&9n8i;r6bC9C!^x0wmgVY>ty z3&H#x5lO;|_dU_}-h1?1WX&FRinC0m|FPl^4KbHGr`(da=n}`vS0Y zzMJ-q$T(06lg>5qQlmbg6v*WI4_>O^x{gxfK=}=MpCU;Rf!EvNRyn*5g%IPlI-fCG z_(<#SYnG_VrswGZaAm;ZFC7{`x);nbdJ4>)SXP@(nuh9bX8=kwyUK9JtScw9Dr@h( zw5j0KMetSao57U5WHYwuIu&tDSei0qGl6ne*Wpq0j2RYYY~cJ^SeG>LpaQC!KqtohW^f?tr~|Ewy0&J zJ7FQZanN*hgtvoy=lA^WE~RC0Cv1ZW5RmV#j_c3#>RnP`#Mfi%(8@|I?pwc_Mv91{ zT4HVN{%DC>inz~iO8~7ciwO6134zIMhba0erNdM$5X+cICS-l3v8irwQVpWr?|Jn` zmCG*oDUlIf%^gJOmy&TO6T*^AYEBaBi8|iRX|Jbw(L9FDnU|AF6TNMF{u1_8eBS!r zAXFNV%ino1{6%BI4b=%)kdKOPX6Hz4c=i7CC}VB#wbCL@<>_*-quSR>=j-$+`$QmC zVfL#x9pwMYdMz zY5y`pE*)%y^lAsa&rWd=-EeD2ip!b%X|aA_NO=E*o~UgdKb3&wGvU(C@g` zB~tz^$@kAU@8F^&{Utg*`(`RRj_SnAAJw^4bpEXFD=Ys~(fZj&PTsY@?tEvzwDpTY z3Gh^fF~#Q3mU^-i@pB_y#0uqEHo3+}-FKp85Jpb*YImN0>Mu0Fx;}ILmV4K3y?&{e z5)Ny{BGC<5^}a`^ei={yAJxFWV@Gen-(etDiLA~*y;BMzeIVEkyA0`Rr4?@Q<53+O z0J2NjvyIYI{C*#hUp__I3-lKsxBTHE=26wIc_2&72TStAFC)<)rBC*#4p87-5MnA0 zfwUShLblvQjre{86(2DG&lWJLvF=G0W0S*QLb^QI$Wh#7W5f6a4uKZV8{^qTZgXWI zTMo+u>U|Qn>W}0W`!X^}{;R@9l?{;vs#wNCb{+y@7tjMf;fCWsf?D=+P&gIIE};v2 z^TL-iAx3e^*-damjJwL8sugib+Ree1`%;O#Rnf|6bcHJ)a24tg4c4FX~7L zG>0s=#grs}{_-UYw1u`lJ+RTeJGZd#hWdk-Fdz{rTAZ9aw6GB(1fLUQC>AI+o;`bp z1g+ZE`oD#A#${(x{(HJZQRq8zwamse@x2PifzaLZ(I1p4~=ki*W;FdC!PgGk22^1-Bi!@qZ>0>Xq6E8|4wMUmEP4@ z^$>#Z8Ss&uFgl>0n#;|?i01Yv#C;TaP7E}_t17DFI3Qz%*W1<<~Z>uSR(Yo|Ee#j0%&VSKd3m^zQ-MZ^gP1J1zvl_oBC5%S56M zY0oLFl4J=WSc#qmI!o}nx$O5{zGIK{;*Y$$ds%sucrxJ^X7A`s12g^nuC1+Cgk)Ug zef73~KMPsl5LtKX&N#Q6#p12@xtFB?gdUM4xT{yfA+K&KiA0d|TEAH*jP(8Y@pj?M zQMx??hXjoLURP&l4QT7(Ue>lsY}y1~P4lgfCK&bh=`UVDtP{&qy9Cc^|MyNkSQXPM z@@7mI_EQQURU}-Z2*g+#yrzD>d3!HbWPGX_zQ=uD>K)Q3X}FNXE~|3!-z`HP{e0te zFGR#(N^ty9U}G$gxufXFK)BR|GU~r|2bsNg&+b8P#Q3COFGoA}8IRlV0bA+hjBMHb z2&RAjI|;;CHnu?adjxAr$HbM|KbeF_&RL8c{HKFIq$BSB{O>bO8N%a99sR2Du!rS+ zCjOTQkG%GB>vnFKq~=;{b=h$`WMx~rnEbc5V^ost?Y{`XEbobk5dW#fWsQQ^dqT$D zie}}{*H#{ZX^a0I)v-cqLSN~udqCam519-rgpg#%QB|8pYX8e2;dovY}1y2DppYr2qa~E7?ur-#=YeApW?)7)bmfbnoBun5+KVH>oM{ p-*W{DlTZ=g{Qv*)|Emw@2gLra${t@0*S|aS#WVG%sK@5P{|6q@Ashez literal 0 HcmV?d00001 From f072c5f1a1bb607797a85cd43cf498ec541af3ab Mon Sep 17 00:00:00 2001 From: Stefan Rinkes Date: Sun, 18 Apr 2021 18:49:01 +0200 Subject: [PATCH 02/19] OPENSSH KeyReader for more keys (#614) * OPENSSH KeyReader for more keys Add support to parse OpenSSH Keys with ECDSA 256/384/521 and RSA. https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key Change-Id: Iaa9cce0f2522e5fee377a82cb252f81f0b7cc563 * Fix ED25519Key KeyLength * Fix ED25519 PubKey-auth LeadingZeros of BigInteger-Conversion have to be removed before sending the Key. --- README.md | 2 +- .../Classes/PrivateKeyFileTest.cs | 98 ++++++++++++++-- .../Data/Key.OPENSSH.ECDSA.Encrypted.txt | 9 ++ .../Data/Key.OPENSSH.ECDSA.txt | 9 ++ .../Data/Key.OPENSSH.ECDSA384.Encrypted.txt | 11 ++ .../Data/Key.OPENSSH.ECDSA384.txt | 10 ++ .../Data/Key.OPENSSH.ECDSA521.Encrypted.txt | 12 ++ .../Data/Key.OPENSSH.ECDSA521.txt | 12 ++ .../Data/Key.OPENSSH.RSA.Encrypted.txt | 28 +++++ .../Data/Key.OPENSSH.RSA.txt | 27 +++++ .../Renci.SshNet.Tests.csproj | 8 ++ src/Renci.SshNet/PrivateKeyFile.cs | 111 ++++++++++++------ .../Security/Cryptography/ED25519Key.cs | 4 +- .../Security/Cryptography/RsaKey.cs | 9 ++ src/Renci.SshNet/Security/KeyHostAlgorithm.cs | 7 +- 15 files changed, 309 insertions(+), 48 deletions(-) mode change 100644 => 100755 README.md create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.Encrypted.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.Encrypted.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.Encrypted.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.Encrypted.txt create mode 100644 src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.txt diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b44ae97bb..242c6dc6a --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ the missing test once you figure things out. 🤓 * RSA in OpenSSL PEM and ssh.com format * DSA in OpenSSL PEM and ssh.com format * ECDSA 256/384/521 in OpenSSL PEM format -* ED25519 in OpenSSH key format +* ECDSA 256/384/521, ED25519 and RSA in OpenSSH key format Private keys can be encrypted using one of the following cipher methods: * DES-EDE3-CBC diff --git a/src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs b/src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs index 99434d71a..130e9922d 100644 --- a/src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs +++ b/src/Renci.SshNet.Tests/Classes/PrivateKeyFileTest.cs @@ -545,13 +545,10 @@ public void ConstructorWithFileNameAndPassPhraseShouldBeAbleToReadFileThatIsShar } } - /// - /// A test for opening an openssh v1 keyfile where there is no passphrase. - /// [TestMethod()] [Owner("bhalbright")] [TestCategory("PrivateKey")] - public void TestOpenSshV1KeyFileNoPassphrase() + public void Test_PrivateKey_OPENSSH_ED25519() { using (var stream = GetData("Key.OPENSSH.ED25519.txt")) { @@ -559,13 +556,10 @@ public void TestOpenSshV1KeyFileNoPassphrase() } } - /// - /// A test for opening an openssh v1 keyfile where there is a passphrase. - /// [TestMethod()] [Owner("bhalbright")] [TestCategory("PrivateKey")] - public void TestOpenSshV1KeyFileWithPassphrase() + public void Test_PrivateKey_OPENSSH_ED25519_ENCRYPTED() { using (var stream = GetData("Key.OPENSSH.ED25519.Encrypted.txt")) { @@ -573,6 +567,94 @@ public void TestOpenSshV1KeyFileWithPassphrase() } } + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_RSA() + { + using (var stream = GetData("Key.OPENSSH.RSA.txt")) + { + new PrivateKeyFile(stream); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_RSA_ENCRYPTED() + { + using (var stream = GetData("Key.OPENSSH.RSA.Encrypted.txt")) + { + new PrivateKeyFile(stream, "12345"); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA() + { + using (var stream = GetData("Key.OPENSSH.ECDSA.txt")) + { + new PrivateKeyFile(stream); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA_ENCRYPTED() + { + using (var stream = GetData("Key.OPENSSH.ECDSA.Encrypted.txt")) + { + new PrivateKeyFile(stream, "12345"); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA384() + { + using (var stream = GetData("Key.OPENSSH.ECDSA384.txt")) + { + new PrivateKeyFile(stream); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA384_ENCRYPTED() + { + using (var stream = GetData("Key.OPENSSH.ECDSA384.Encrypted.txt")) + { + new PrivateKeyFile(stream, "12345"); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA521() + { + using (var stream = GetData("Key.OPENSSH.ECDSA521.txt")) + { + new PrivateKeyFile(stream); + } + } + + [TestMethod()] + [Owner("darinkes")] + [TestCategory("PrivateKey")] + public void Test_PrivateKey_OPENSSH_ECDSA521_ENCRYPTED() + { + using (var stream = GetData("Key.OPENSSH.ECDSA521.Encrypted.txt")) + { + new PrivateKeyFile(stream, "12345"); + } + } + private void SaveStreamToFile(Stream stream, string fileName) { var buffer = new byte[4000]; diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.Encrypted.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.Encrypted.txt new file mode 100644 index 000000000..ab76db4a2 --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.Encrypted.txt @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCPSPglZ3 +w/7DmCJxYohONLAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz +dHAyNTYAAABBBK6YY2NwwLDSMnJTD+a4OfitCDuG/MnY/AstPgh54xMrZF6Qr0U1H6kRMK +Y6JJsj31CI97qDYrnTA00Sx5Jy6ywAAACwq4qisorVCP6yvrmf/fcPacX4+FVEmrHNn3fW +TiYsat7oKoItqTiDaHkIloSX93ue3fzcKXpGPR/qnpu4SezkhL9Uk6ntiwO4coB/kbEnjk +IFY6ZK0HENRXkdIuDG9qmoB0wjVPJ6L9e5RWZwiCPvNI2O60bpKOUs+tUSah1W7eTWy5Ss +ttdTgmwqS84c5+uitK1DJh2jsDqfdGm7h1XpDJsRmIEXxTVu/EdtD0hZ/x4= +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.txt new file mode 100644 index 000000000..94f16bcbd --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA.txt @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSP3ZTb37LFvSmKweu03A5s/cwcw3+3 +jL1LqQK6D929xY1J2J6S91LXOBpBfz4l+8Ng7sWhu9P/hF/wmB2QRygrAAAAqMq583bKuf +N2AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI/dlNvfssW9KYrB +67TcDmz9zBzDf7eMvUupAroP3b3FjUnYnpL3Utc4GkF/PiX7w2DuxaG70/+EX/CYHZBHKC +sAAAAhALVqID3K/N7IazKNbhrg09r7rLLtjy81RLV+VDxloQnxAAAAC3NyaW5rZXNATkVP +AQIDBA== +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.Encrypted.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.Encrypted.txt new file mode 100644 index 000000000..500654500 --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.Encrypted.txt @@ -0,0 +1,11 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABAMZphcrt +UKJMlSabtzt2GdAAAAEAAAAAEAAACIAAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlz +dHAzODQAAABhBFL5NEL9uRhgkF2q+8m58EvtZq4mDGgcVEzafPRuNIn1018m9KuqNpOQ6d ++435n+MRYThe4MUdijSIDuopX2i14Z35oKZ9x2LsV+RxQczjmbnoWZdvgcvdOo6jiJdY7X +JwAAAOBvXOaTq8vPRy7y5BBzr26QAYouJfGprYOqpywiIAZaICu0FJ8EXmmen6310CTG6Z +CZ4VhC5MWCWRYTaOnPNn8FvGqo2bxEqWZmyZfVvv1Z35MtSAZEfwgfXaOZKJ/lPKsRndg5 +okpqNU1aG2u+4J7eZ7QyCD/1RCCEL5wwVcrDeuMkTDPpnJc1NEGz8HbfcZ5xZavrz6Wa9t +tX7pFICqK9IIeOGMJ2WRXR6sQGyag+jNn9KmsIya7hkNJVeZeY2GKAk2s/0vxfYx9RFD55 +ewB34oHyTdxAQT3L+FZT6XfRHw== +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.txt new file mode 100644 index 000000000..e5e6e06a9 --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA384.txt @@ -0,0 +1,10 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS +1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRTP1DMXoHgW+RX+S/NxUEElou1cmLD +6CEiR+zpzaGG6mzl6LhUY+Z3f2M3u4u7tcM8TgB/jiHbnI9TaeN5QK4HX1D9DXkH5RhfnL +frm3kCTNoCFKd0Wa/QAvKrlNKiRi8AAADYlABjHJQAYxwAAAATZWNkc2Etc2hhMi1uaXN0 +cDM4NAAAAAhuaXN0cDM4NAAAAGEEUz9QzF6B4FvkV/kvzcVBBJaLtXJiw+ghIkfs6c2hhu +ps5ei4VGPmd39jN7uLu7XDPE4Af44h25yPU2njeUCuB19Q/Q15B+UYX5y365t5AkzaAhSn +dFmv0ALyq5TSokYvAAAAMAXLUgK32yWzUrpeLzpdFB2/eiNnkxQlu5OneTPukKcZYclfgo +jv0YHK5LCvAtF8lwAAAAtzcmlua2VzQE5FTwECAwQF +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.Encrypted.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.Encrypted.txt new file mode 100644 index 000000000..da831cf9c --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.Encrypted.txt @@ -0,0 +1,12 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABBWjIyzbM +MQ3UPE8BiQ0n4LAAAAEAAAAAEAAACsAAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlz +dHA1MjEAAACFBAH9BVM6bRhbELtgdMGsin5lM42R2EWoT+6Akakl5rQy2tHHLIYGLEfaqI ++0iUo2V6MxEf9w0hVz6SEsF+yDgyrYPQCIieaB1oBvIl+PZmL1XsuAXs2uMRsNJb4myGU/ +DiekxqzIPa0LMrBZ4xmErcn5Gazkw1EA0B3HoaW5wj+geI/efQAAARDi+GGTYH1T+5Dd8N +EVCiL+J7fm8uP8yAcvQNh3JBYIf1g/GZ0hJDuA47fcTzXEfTGZLGWdgaE8cxIUICpjBoak +EpNS1HyhqYZAt2J8o/14t2GbXczJfoQLOIQl2S1zXQ9shof12odu9DGcBhSAz9hswlndBE +d99uCz/ymzwQ0i2Pp+urUXo7+YXB6HMh9YTMeGQAiDJFO3NPDqDczfUECtTUkQMhy8r06m +hAp/oZ6K1KBbZzdc0xyqDePKAqqyHnN4FD7Wfv11SWoOhlUcEVg2ZvNj/O+CsoWzMpN+dt +DPKZHmH/kegWKBsdtAC9f5Hg3b2oQAK0pKghms1+/J9iilnIMwv80CPzGdv0YAG9Vx5w== +-----END OPENSSH PRIVATE KEY----- diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.txt new file mode 100644 index 000000000..0ad09eb24 --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.ECDSA521.txt @@ -0,0 +1,12 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS +1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQAa7p4WVga+08qu160BrdzKyRNJMQC +eGhFluNdq73/uaW3qlqoEiaNtc5uB7HHyjCWQTmfzrSRLRZ7YBwUancwyh4Aq6gBgGsXVz +wNvY3kxRDlGrSfMmsHlXz41dgw9wm1fBcf97niexRQ/xGlhkyf7IYlQ/s5BpXF2lS9l0H5 +hBippRgAAAEI/9prf//aa38AAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ +AAAIUEAGu6eFlYGvtPKrtetAa3cyskTSTEAnhoRZbjXau9/7mlt6paqBImjbXObgexx8ow +lkE5n860kS0We2AcFGp3MMoeAKuoAYBrF1c8Db2N5MUQ5Rq0nzJrB5V8+NXYMPcJtXwXH/ +e54nsUUP8RpYZMn+yGJUP7OQaVxdpUvZdB+YQYqaUYAAAAQXwQnI20tNxwLKHPMDmumblD +b0sBqW5Y9248L//x4sWFrkjk6k1LcZno9KLqz8+tIFMJ5sji+axRoUZCXb3cIPzPAAAAC3 +NyaW5rZXNATkVP +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.Encrypted.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.Encrypted.txt new file mode 100644 index 000000000..b9eed58be --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.Encrypted.txt @@ -0,0 +1,28 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABCoWhCSaG +psKT80oPIOAlqJAAAAEAAAAAEAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQCxOfnmxC1g +mmX18LCBG/X73BoCXQEBEAJz3V9w0FMTgUBebK3fkfOMLNzWn5aMR608wQHOEPYhHffCJf +dJR6lUWLHZz5+EZRfM9oHpysMtToYQoGtb9xM7D5J3lnWZgSea2R7xSeqpClN5nQUMGu8y +2d2S3g9o1vrTdeu71u09QFOx2AXBPUmCjpCuBlNyYEEQMfRMtQ6PDbPdvLM1uylbQqB+/6 +jMsCyEFvlLit9GcZ7ItKQN+jsZNmP+f7ytVXLsZTjPLd5mWWrf6T1T1Xt9DBoLXnMrmDiC +f/EXiTYonIO6B0FHvNUCrDzZ7rxIebqePLes1Q2yoUqmC8g+cww3AAADwNRNGSnB7cRpgU +BxdyC0ofj0hUONXjmoT+OGPph9lgZMUnzcon9Z1bpsJuMoRXL14Cdbds7YPmw1YB94Uc+S +8QexLJG0wGel2yvzJhU+QFsLeVRS4tayERFXGCoVpu7RunEYy+hvaiX5CD+luEkiarfj9I +N8+9QUMhDYkELwWBV4rde18Vr8m1P1FuFgqikY0TfSKUGCkvjl4FvDxrxqsewaEkkzwRTI +PhOFCCM5jBPWE+uWVcwKoidvAqcNbmwIzDNZGwXtrAvYYzZa62C/MNLHuFU1weuJiM8sYa +6iKrk681BrrpGcSEZEXd41CFY3BWlIDTozrWn03xFlIpeLG2YMPcuYqFhR/41BJfa+fW5B +Ei0SuUx2xjdRiamqpPku4H6ulkjl0KlFCr976Y2V1JZMQh7bd0huubmf4P4poBk6ZgGpSf +snhcv1HjCVkvfA2yhOcXogzK2HOZgDS5sdSb/kUGURdjlj6ccSzc3OYaHAy9gZXj8Q58pA +4KrXTDlCJ9BTR8PIND54j6gMKu5ijX0TP9nJf/hG9GXx+Xss8T3xdPxdNBapPCcuxGZGJN +H+KFqrpmZYHm0evqFPS7BCUp2VvID6SMgrTYiH0IIbMHLStfdNchtn3EudMbW9vRhxg3Do +npT7Px2JYp87PNoHg2eOx0yGy9r81n2+Wi7SpGCWD8MFfxqd4JIQ8+zjrIRAA1q53uuSUh +m/hlmJWEjQWmcBw5bKrOU0CfGGoT3o6HWYRQ9d5+kKeoS+dOINxxf80G5b7vOrE3PbFxT3 +W8zwRd90Msr3LXgPaN0V4RJeBX38e0EvVbArL2MgSs/BC5aID0N0Sqiu+13AqqNYxj6RH2 +FA7FN+BBa16fvdi5h5kNnZUrQUKOAImjEE494O8uGKQImviGqB5PY6DJqHPTtn7RSwFx9E +rR7nbAZPTucIN/OIfURxTedhROk0PXjWnwpjuz+UpaMRWqgWTv3bLOuqorqMLibAFLRQEQ +6pR0wbmTpTfEW1jNmAohxB4N14YdSfhThzkCAgpQW6UCLc83y3EDzQFi5862a+2ixULKhK +220tZRk2GU7OFAPRpgQ/sxptGqZbNdOV80wk1MgykoFkoptRkm7bfJcdLHZnP7E6yU0ssP +rCbQlfD0/dD2QE/7HqxHsipNNuEagULjK6WUYXkpx1Siq2vecjZw8dNp7EBh+KlujEm+Dr +R7KFdFCw8DUwrzXwfMIogeRVbW8H0/fQEqsX5oPLTEOnNBjzf8pHush7CCrprbo0ZK3xFp +Vr3LUCoA== +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.txt b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.txt new file mode 100644 index 000000000..893001ebb --- /dev/null +++ b/src/Renci.SshNet.Tests/Data/Key.OPENSSH.RSA.txt @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA7W7Oigi7Hj1msa2l8HimLPzagVmE/CseMKCRxPMTtWTvoZdMt7hf +kthWA7h20a7oSSeH2t7FqeOpVNGFYvRV3BVWsKZJMRcdJiTCZAjH38rYk90XvZ3mKrKN/3 +fcQsh4OiPnWqT6HSqg14oiV8UPtUwnE65skWSxvxt+ELlVpCqG5vE2O/GNDKQE7FzYt6vQ +ihMFSABBqjvau0mjX002KYiCMr6vgl8XYkDA4n5+JyQSQxznnfrL93ZoaqujRP2bT5UhXg +bzr8HFwuqQGvURECZTTI8Biv/6tOIn9x2hEaN6vxDLtXc99E2d6NW6cdriwaGFJ4jgVWDE +5mU006XdPQAAA8jzN6zf8zes3wAAAAdzc2gtcnNhAAABAQDtbs6KCLsePWaxraXweKYs/N +qBWYT8Kx4woJHE8xO1ZO+hl0y3uF+S2FYDuHbRruhJJ4fa3sWp46lU0YVi9FXcFVawpkkx +Fx0mJMJkCMffytiT3Re9neYqso3/d9xCyHg6I+dapPodKqDXiiJXxQ+1TCcTrmyRZLG/G3 +4QuVWkKobm8TY78Y0MpATsXNi3q9CKEwVIAEGqO9q7SaNfTTYpiIIyvq+CXxdiQMDifn4n +JBJDHOed+sv3dmhqq6NE/ZtPlSFeBvOvwcXC6pAa9REQJlNMjwGK//q04if3HaERo3q/EM +u1dz30TZ3o1bpx2uLBoYUniOBVYMTmZTTTpd09AAAAAwEAAQAAAQEA6Xgq+gppzOt9nrts +z5Ajf1tHlSesn7XaYuCRVgPb3mOZSuEW3BUdTa0Sr2fk1nzSBpUrfqnN3idyK2g3bD1sbB +RDgUKR+AaNcCN3TpxfxgyVeJhQLvEkEdovzQRUfwrXRfxmE3jkRGfVbvxylrG8p35xcmXy +del46r2i8dj8gIY3tKp0RMvZ4ZlNbhWHPd5OxyHWL9e3gbOSyIyjQgTKZezhzErS/X/KJ/ +XYqzyBAqNqZ2Rg1kKiHRlHS6KEI2tyFwYfh+Rb6L9xch1SqOtQhTWirmxS25dpGD2jgalX +eyiw8PmuqTiWCqUmUMx6MdF3tFsirr54K4QA9kqMeaRLtQAAAIEAsUQT0Uhq7l0ugTd4Y9 +89bH6eW0fol21/m7B5zkJQepNadUPTs188uvv4inW8n2O3RCanXWHZfCJ1AsR/MEEW2C6Q +DtvqKXHbzfWQlCYSVxB17CjURKa8fNaIAk98zgmNNwO53NBleyrUhPgvm3xt7ACgpzXY5R +wNJL8/a0WOmgwAAACBAP508Op6wWPAwn1JfBZuqQtjcfnJeN4NkYQBdybn0vVu5UdyqSQL +a8hlAzROhA+qJvrlsZgM9h8CyLTyuim8likZHocwO13zBTdVaQ8c2lJvf2uXTIXNZHseS7 +ITkfBiO1hSB4z8RDkOr35mGfdbyJIFAwFZF4Xs8WnQF+vHEadrAAAAgQDu329eCwVFf9g0 +zNHfZu31p0WtErcsRv57fq+UoPtov8nxUF71oOWe5KSGnGtMICI31kBtPhUbvfOmuqNrgJ +BjgjbPQmi0xSAE5L3QuEKRNjlaE3/WadKBwzhJDtauuYk1ifkrdAVp67XyQ5puyuGgVaQB +NPbrxA9g1IbyeL4/9wAAAAtzcmlua2VzQE5FTwECAwQFBg== +-----END OPENSSH PRIVATE KEY----- \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index d7ee81e9a..8ba9f3077 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -35,6 +35,14 @@ + + + + + + + + diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index 31fac7db4..1424134f6 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -26,13 +26,13 @@ namespace Renci.SshNet /// The following private keys are supported: /// /// - /// RSA in OpenSSL PEM and ssh.com format + /// RSA in OpenSSL PEM, ssh.com and OpenSSH key format /// /// /// DSA in OpenSSL PEM and ssh.com format /// /// - /// ECDSA 256/384/521 in OpenSSL PEM format + /// ECDSA 256/384/521 in OpenSSL PEM and OpenSSH key format /// /// /// ED25519 in OpenSSH key format @@ -373,7 +373,7 @@ private static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, strin /// the key file data (i.e. base64 encoded data between the header/footer) /// passphrase or null if there isn't one /// - private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) + private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) { var keyReader = new SshDataReader(keyFileData); @@ -387,8 +387,10 @@ private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) //cipher will be "aes256-cbc" if using a passphrase, "none" otherwise var cipherName = keyReader.ReadString(Encoding.UTF8); + //key derivation function (kdf): bcrypt or nothing var kdfName = keyReader.ReadString(Encoding.UTF8); + //kdf options length: 24 if passphrase, 0 if no passphrase var kdfOptionsLen = (int)keyReader.ReadUInt32(); byte[] salt = null; @@ -407,29 +409,21 @@ private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) throw new SshException("At this time only one public key in the openssh key is supported."); } - //length of first public key section - keyReader.ReadUInt32(); - var keyType = keyReader.ReadString(Encoding.UTF8); - if(keyType != "ssh-ed25519") - { - throw new SshException("openssh key type: " + keyType + " is not supported"); - } - - //read public key - var publicKeyLength = (int)keyReader.ReadUInt32(); //32 - var publicKey = keyReader.ReadBytes(publicKeyLength); + //read public key in ssh-format, but we dont need it + keyReader.ReadString(Encoding.UTF8); //possibly encrypted private key var privateKeyLength = (int)keyReader.ReadUInt32(); var privateKeyBytes = keyReader.ReadBytes(privateKeyLength); //decrypt private key if necessary - if (cipherName == "aes256-cbc") + if (cipherName != "none") { if (string.IsNullOrEmpty(passPhrase)) { throw new SshPassPhraseNullOrEmptyException("Private key is encrypted but passphrase is empty."); } + if (string.IsNullOrEmpty(kdfName) || kdfName != "bcrypt") { throw new SshException("kdf " + kdfName + " is not supported for openssh key file"); @@ -445,14 +439,21 @@ private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) byte[] iv = new byte[16]; Array.Copy(keyiv, 32, iv, 0, 16); - //now that we have the key/iv, use a cipher to decrypt the bytes - var cipher = new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); + AesCipher cipher; + switch (cipherName) + { + case "aes256-cbc": + cipher = new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); + break; + case "aes256-ctr": + cipher = new AesCipher(key, new CtrCipherMode(iv), new PKCS7Padding()); + break; + default: + throw new SshException("Cipher '" + cipherName + "' is not supported for an OpenSSH key."); + } + privateKeyBytes = cipher.Decrypt(privateKeyBytes); } - else if (cipherName != "none") - { - throw new SshException("cipher name " + cipherName + " for openssh key file is not supported"); - } //validate private key length privateKeyLength = privateKeyBytes.Length; @@ -470,22 +471,49 @@ private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) int checkInt1 = (int)privateKeyReader.ReadUInt32(); int checkInt2 = (int)privateKeyReader.ReadUInt32(); if (checkInt1 != checkInt2) - { - throw new SshException("The checkints differed, the openssh key was not correctly decoded."); - } + throw new SshException("The random check bytes of the OpenSSH key do not match (" + checkInt1 + " <->" + checkInt2 + ")."); - //key type, we already know it is ssh-ed25519 - privateKeyReader.ReadString(Encoding.UTF8); + //key type + var keyType = privateKeyReader.ReadString(Encoding.UTF8); - //public key length/bytes (again) - var publicKeyLength2 = (int)privateKeyReader.ReadUInt32(); - privateKeyReader.ReadBytes(publicKeyLength2); - - //length of private and public key (64) - privateKeyReader.ReadUInt32(); - var unencryptedPrivateKey = privateKeyReader.ReadBytes(32); - //public key (again) - privateKeyReader.ReadBytes(32); + Key parsedKey; + byte[] publicKey; + byte[] unencryptedPrivateKey; + switch (keyType) + { + case "ssh-ed25519": + //public key + publicKey = privateKeyReader.ReadBignum2(); + //private key + unencryptedPrivateKey = privateKeyReader.ReadBignum2(); + parsedKey = new ED25519Key(publicKey.Reverse(), unencryptedPrivateKey); + break; +#if FEATURE_ECDSA + case "ecdsa-sha2-nistp256": + case "ecdsa-sha2-nistp384": + case "ecdsa-sha2-nistp521": + // curve + int len = (int)privateKeyReader.ReadUInt32(); + var curve = Encoding.ASCII.GetString(privateKeyReader.ReadBytes(len)); + //public key + publicKey = privateKeyReader.ReadBignum2(); + //private key + unencryptedPrivateKey = privateKeyReader.ReadBignum2(); + parsedKey = new EcdsaKey(curve, publicKey, unencryptedPrivateKey.TrimLeadingZeros()); + break; +#endif + case "ssh-rsa": + var modulus = privateKeyReader.ReadBignum(); //n + var exponent = privateKeyReader.ReadBignum(); //e + var d = privateKeyReader.ReadBignum(); //d + var inverseQ = privateKeyReader.ReadBignum(); // iqmp + var p = privateKeyReader.ReadBignum(); //p + var q = privateKeyReader.ReadBignum(); //q + parsedKey = new RsaKey(modulus, exponent, d, p, q, inverseQ); + break; + default: + throw new SshException("OpenSSH key type '" + keyType + "' is not supported."); + } //comment, we don't need this but we could log it, not sure if necessary var comment = privateKeyReader.ReadString(Encoding.UTF8); @@ -501,7 +529,7 @@ private ED25519Key ParseOpenSshV1Key(byte [] keyFileData, string passPhrase) } } - return new ED25519Key(publicKey.Reverse(), unencryptedPrivateKey); + return parsedKey; } #region IDisposable Members @@ -594,6 +622,17 @@ public BigInteger ReadBigIntWithBits() return new BigInteger(bytesArray.Reverse()); } + public BigInteger ReadBignum() + { + return new BigInteger(ReadBignum2().Reverse()); + } + + public byte[] ReadBignum2() + { + var length = (int)base.ReadUInt32(); + return base.ReadBytes(length); + } + protected override void LoadData() { } diff --git a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs index 83ac1c8cd..deb4b1181 100644 --- a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs @@ -33,7 +33,7 @@ public override BigInteger[] Public { get { - return new BigInteger[] { publicKey.ToBigInteger() }; + return new BigInteger[] { publicKey.ToBigInteger2() }; } set { @@ -51,7 +51,7 @@ public override int KeyLength { get { - return PublicKey.Length; + return PublicKey.Length * 8; } } diff --git a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs index 6d8a55534..ba5b17464 100644 --- a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs @@ -9,6 +9,15 @@ namespace Renci.SshNet.Security /// public class RsaKey : Key, IDisposable { + + /// + /// Gets the Key String. + /// + public override string ToString() + { + return "ssh-rsa"; + } + /// /// Gets the modulus. /// diff --git a/src/Renci.SshNet/Security/KeyHostAlgorithm.cs b/src/Renci.SshNet/Security/KeyHostAlgorithm.cs index ca94fa70e..11717197b 100644 --- a/src/Renci.SshNet/Security/KeyHostAlgorithm.cs +++ b/src/Renci.SshNet/Security/KeyHostAlgorithm.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Renci.SshNet.Common; +using Renci.SshNet.Security.Chaos.NaCl; namespace Renci.SshNet.Security { @@ -101,7 +102,11 @@ private set _keys = new List(value.Length); foreach (var key in value) { - _keys.Add(key.ToByteArray().Reverse()); + var keyData = key.ToByteArray().Reverse(); + if (Name == "ssh-ed25519") + keyData = keyData.TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes); + + _keys.Add(keyData); } } } From 583a9cea6a2cacdc63bb353ed2f5867613f24271 Mon Sep 17 00:00:00 2001 From: wxtsxt Date: Wed, 8 Sep 2021 18:26:56 +0200 Subject: [PATCH 03/19] Add interface to SftpFile #120 (#812) * Create ISftpFile interface. SftpFile sealed. Return ISftpFile from SftpClient instead of SftpFile. Make ISftpClient interface disposable. Co-authored-by: Wojciech Swieboda --- .../Renci.SshNet.Silverlight.csproj | 3 + .../Renci.SshNet.Silverlight5.csproj | 3 + .../Classes/SftpClientTest.cs | 12 +- .../Renci.SshNet.UAP10.csproj | 3 + .../Renci.SshNet.WindowsPhone.csproj | 3 + .../Renci.SshNet.WindowsPhone8.csproj | 3 + src/Renci.SshNet/ISftpClient.cs | 10 +- src/Renci.SshNet/Sftp/ISftpFile.cs | 233 ++++++++++++++++++ src/Renci.SshNet/Sftp/SftpFile.cs | 2 +- .../Sftp/SftpListDirectoryAsyncResult.cs | 2 +- src/Renci.SshNet/SftpClient.cs | 23 +- 11 files changed, 275 insertions(+), 22 deletions(-) create mode 100644 src/Renci.SshNet/Sftp/ISftpFile.cs diff --git a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj b/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj index beeef21a0..7505a175a 100644 --- a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj +++ b/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj @@ -1358,6 +1358,9 @@ Sftp\SftpFile.cs + + Sftp\ISftpFile.cs + Sftp\SftpFileAttributes.cs diff --git a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj b/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj index 93b950edc..cff69e1cd 100644 --- a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj +++ b/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj @@ -1364,6 +1364,9 @@ Sftp\SftpFile.cs + + Sftp\ISftpFile.cs + Sftp\SftpFileAttributes.cs diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs index f562f66bb..8f84546bf 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs @@ -562,8 +562,8 @@ public void EndListDirectoryTest() ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value IAsyncResult asyncResult = null; // TODO: Initialize to an appropriate value - IEnumerable expected = null; // TODO: Initialize to an appropriate value - IEnumerable actual; + IEnumerable expected = null; // TODO: Initialize to an appropriate value + IEnumerable actual; actual = target.EndListDirectory(asyncResult); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); @@ -702,8 +702,8 @@ public void GetTest() ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value string path = string.Empty; // TODO: Initialize to an appropriate value - SftpFile expected = null; // TODO: Initialize to an appropriate value - SftpFile actual; + ISftpFile expected = null; // TODO: Initialize to an appropriate value + ISftpFile actual; actual = target.Get(path); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); @@ -802,8 +802,8 @@ public void ListDirectoryTest() SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value string path = string.Empty; // TODO: Initialize to an appropriate value Action listCallback = null; // TODO: Initialize to an appropriate value - IEnumerable expected = null; // TODO: Initialize to an appropriate value - IEnumerable actual; + IEnumerable expected = null; // TODO: Initialize to an appropriate value + IEnumerable actual; actual = target.ListDirectory(path, listCallback); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); diff --git a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj b/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj index d0eb423a2..a1f0c994f 100644 --- a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj +++ b/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj @@ -1440,6 +1440,9 @@ Sftp\SftpFile.cs + + Sftp\ISftpFile.cs + Sftp\SftpFileAttributes.cs diff --git a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj b/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj index 317dbc845..f8342e11b 100644 --- a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj +++ b/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj @@ -1343,6 +1343,9 @@ Sftp\SftpFile.cs + + Sftp\ISftpFile.cs + Sftp\SftpFileAttributes.cs diff --git a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj b/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj index f34c1d8e8..fb301e597 100644 --- a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj +++ b/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj @@ -1396,6 +1396,9 @@ Sftp\SftpFile.cs + + Sftp\ISftpFile.cs + Sftp\SftpFileAttributes.cs diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index b1212cfea..62f432491 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -10,7 +10,7 @@ namespace Renci.SshNet /// /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH. /// - public interface ISftpClient + public interface ISftpClient : IDisposable { /// /// Gets or sets the maximum size of the buffer in bytes. @@ -525,7 +525,7 @@ public interface ISftpClient /// A list of files. /// /// The object did not come from the corresponding async method on this type.-or- was called multiple times with the same . - IEnumerable EndListDirectory(IAsyncResult asyncResult); + IEnumerable EndListDirectory(IAsyncResult asyncResult); /// /// Ends the synchronize directories. @@ -568,13 +568,13 @@ public interface ISftpClient /// /// The path. /// - /// A reference to file object. + /// A reference to file object. /// /// Client is not connected. /// was not found on the remote host. /// is null. /// The method was called after the client was disposed. - SftpFile Get(string path); + ISftpFile Get(string path); /// /// Gets the of the file on the path. @@ -666,7 +666,7 @@ public interface ISftpClient /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - IEnumerable ListDirectory(string path, Action listCallback = null); + IEnumerable ListDirectory(string path, Action listCallback = null); /// /// Opens a on the specified path with read/write access. diff --git a/src/Renci.SshNet/Sftp/ISftpFile.cs b/src/Renci.SshNet/Sftp/ISftpFile.cs new file mode 100644 index 000000000..60c4a7a52 --- /dev/null +++ b/src/Renci.SshNet/Sftp/ISftpFile.cs @@ -0,0 +1,233 @@ +using System; + +namespace Renci.SshNet.Sftp +{ + /// + /// Represents SFTP file information + /// + public interface ISftpFile + { + /// + /// Gets the file attributes. + /// + SftpFileAttributes Attributes { get; } + + /// + /// Gets the full path of the directory or file. + /// + string FullName { get; } + + /// + /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists. + /// Otherwise, the Name property gets the name of the directory. + /// + string Name { get; } + + /// + /// Gets or sets the time the current file or directory was last accessed. + /// + /// + /// The time that the current file or directory was last accessed. + /// + DateTime LastAccessTime { get; set; } + + /// + /// Gets or sets the time when the current file or directory was last written to. + /// + /// + /// The time the current file was last written. + /// + DateTime LastWriteTime { get; set; } + + /// + /// Gets or sets the time, in coordinated universal time (UTC), the current file or directory was last accessed. + /// + /// + /// The time that the current file or directory was last accessed. + /// + DateTime LastAccessTimeUtc { get; set; } + + /// + /// Gets or sets the time, in coordinated universal time (UTC), when the current file or directory was last written to. + /// + /// + /// The time the current file was last written. + /// + DateTime LastWriteTimeUtc { get; set; } + + /// + /// Gets or sets the size, in bytes, of the current file. + /// + /// + /// The size of the current file in bytes. + /// + long Length { get; } + + /// + /// Gets or sets file user id. + /// + /// + /// File user id. + /// + int UserId { get; set; } + + /// + /// Gets or sets file group id. + /// + /// + /// File group id. + /// + int GroupId { get; set; } + + /// + /// Gets a value indicating whether file represents a socket. + /// + /// + /// true if file represents a socket; otherwise, false. + /// + bool IsSocket { get; } + + /// + /// Gets a value indicating whether file represents a symbolic link. + /// + /// + /// true if file represents a symbolic link; otherwise, false. + /// + bool IsSymbolicLink { get; } + + /// + /// Gets a value indicating whether file represents a regular file. + /// + /// + /// true if file represents a regular file; otherwise, false. + /// + bool IsRegularFile { get; } + + /// + /// Gets a value indicating whether file represents a block device. + /// + /// + /// true if file represents a block device; otherwise, false. + /// + bool IsBlockDevice { get; } + + /// + /// Gets a value indicating whether file represents a directory. + /// + /// + /// true if file represents a directory; otherwise, false. + /// + bool IsDirectory { get; } + + /// + /// Gets a value indicating whether file represents a character device. + /// + /// + /// true if file represents a character device; otherwise, false. + /// + bool IsCharacterDevice { get; } + + /// + /// Gets a value indicating whether file represents a named pipe. + /// + /// + /// true if file represents a named pipe; otherwise, false. + /// + bool IsNamedPipe { get; } + + /// + /// Gets or sets a value indicating whether the owner can read from this file. + /// + /// + /// true if owner can read from this file; otherwise, false. + /// + bool OwnerCanRead { get; set; } + + /// + /// Gets or sets a value indicating whether the owner can write into this file. + /// + /// + /// true if owner can write into this file; otherwise, false. + /// + bool OwnerCanWrite { get; set; } + + /// + /// Gets or sets a value indicating whether the owner can execute this file. + /// + /// + /// true if owner can execute this file; otherwise, false. + /// + bool OwnerCanExecute { get; set; } + + /// + /// Gets or sets a value indicating whether the group members can read from this file. + /// + /// + /// true if group members can read from this file; otherwise, false. + /// + bool GroupCanRead { get; set; } + + /// + /// Gets or sets a value indicating whether the group members can write into this file. + /// + /// + /// true if group members can write into this file; otherwise, false. + /// + bool GroupCanWrite { get; set; } + + /// + /// Gets or sets a value indicating whether the group members can execute this file. + /// + /// + /// true if group members can execute this file; otherwise, false. + /// + bool GroupCanExecute { get; set; } + + /// + /// Gets or sets a value indicating whether the others can read from this file. + /// + /// + /// true if others can read from this file; otherwise, false. + /// + bool OthersCanRead { get; set; } + + /// + /// Gets or sets a value indicating whether the others can write into this file. + /// + /// + /// true if others can write into this file; otherwise, false. + /// + bool OthersCanWrite { get; set; } + + /// + /// Gets or sets a value indicating whether the others can execute this file. + /// + /// + /// true if others can execute this file; otherwise, false. + /// + bool OthersCanExecute { get; set; } + + /// + /// Sets file permissions. + /// + /// The mode. + void SetPermissions(short mode); + + /// + /// Permanently deletes a file on remote machine. + /// + void Delete(); + + /// + /// Moves a specified file to a new location on remote machine, providing the option to specify a new file name. + /// + /// The path to move the file to, which can specify a different file name. + /// is null. + void MoveTo(string destFileName); + + /// + /// Updates file status on the server. + /// + void UpdateStatus(); + } +} \ No newline at end of file diff --git a/src/Renci.SshNet/Sftp/SftpFile.cs b/src/Renci.SshNet/Sftp/SftpFile.cs index cfcc37a2f..6356d26ce 100644 --- a/src/Renci.SshNet/Sftp/SftpFile.cs +++ b/src/Renci.SshNet/Sftp/SftpFile.cs @@ -7,7 +7,7 @@ namespace Renci.SshNet.Sftp /// /// Represents SFTP file information /// - public class SftpFile + public sealed class SftpFile : ISftpFile { private readonly ISftpSession _sftpSession; diff --git a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs index cb7b60132..2b791e54c 100644 --- a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs @@ -7,7 +7,7 @@ namespace Renci.SshNet.Sftp /// /// Encapsulates the results of an asynchronous directory list operation. /// - public class SftpListDirectoryAsyncResult : AsyncResult> + public class SftpListDirectoryAsyncResult : AsyncResult> { /// /// Gets the number of files read so far. diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index 3c22290d0..d0cb449d6 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -469,7 +469,7 @@ public void SymbolicLink(string path, string linkPath) /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - public IEnumerable ListDirectory(string path, Action listCallback = null) + public IEnumerable ListDirectory(string path, Action listCallback = null) { CheckDisposed(); @@ -526,7 +526,7 @@ public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, /// A list of files. /// /// The object did not come from the corresponding async method on this type.-or- was called multiple times with the same . - public IEnumerable EndListDirectory(IAsyncResult asyncResult) + public IEnumerable EndListDirectory(IAsyncResult asyncResult) { var ar = asyncResult as SftpListDirectoryAsyncResult; @@ -542,13 +542,13 @@ public IEnumerable EndListDirectory(IAsyncResult asyncResult) /// /// The path. /// - /// A reference to file object. + /// A reference to file object. /// /// Client is not connected. /// was not found on the remote host. /// is null. /// The method was called after the client was disposed. - public SftpFile Get(string path) + public ISftpFile Get(string path) { CheckDisposed(); @@ -1920,7 +1920,7 @@ private IEnumerable InternalSynchronizeDirectories(string sourcePath, #region Existing Files at The Destination var destFiles = InternalListDirectory(destinationPath, null); - var destDict = new Dictionary(); + var destDict = new Dictionary(); foreach (var destFile in destFiles) { if (destFile.IsDirectory) @@ -1986,7 +1986,7 @@ private IEnumerable InternalSynchronizeDirectories(string sourcePath, /// /// is null. /// Client not connected. - private IEnumerable InternalListDirectory(string path, Action listCallback) + private IEnumerable InternalListDirectory(string path, Action listCallback) { if (path == null) throw new ArgumentNullException("path"); @@ -2003,14 +2003,19 @@ private IEnumerable InternalListDirectory(string path, Action lis if (!basePath.EndsWith("/")) basePath = string.Format("{0}/", fullPath); - var result = new List(); + var result = new List(); var files = _sftpSession.RequestReadDir(handle); while (files != null) { - result.AddRange(from f in files - select new SftpFile(_sftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}", basePath, f.Key), f.Value)); + foreach (var f in files) + { + result.Add(new SftpFile( + _sftpSession, + string.Format(CultureInfo.InvariantCulture, "{0}{1}", basePath, f.Key), + f.Value)); + } // Call callback to report number of files read if (listCallback != null) From 30d79c7b316ae5cc7ba590bf6537e684e4a8216b Mon Sep 17 00:00:00 2001 From: Igor Milavec Date: Sun, 28 Nov 2021 15:42:04 +0100 Subject: [PATCH 04/19] Start MessageListener with ThreadAbstraction.ExecuteThreadLongRunning (#902) * Fix Thread pool exhaustion due to MessageListener running on ThreadPool * Mark long running thread as background --- src/Renci.SshNet/Abstractions/ThreadAbstraction.cs | 9 +++++++-- src/Renci.SshNet/Session.cs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs b/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs index ee21ec7ef..8c344404b 100644 --- a/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs @@ -21,12 +21,17 @@ public static void Sleep(int millisecondsTimeout) public static void ExecuteThreadLongRunning(Action action) { + if (action == null) + throw new ArgumentNullException("action"); + #if FEATURE_THREAD_TAP var taskCreationOptions = System.Threading.Tasks.TaskCreationOptions.LongRunning; System.Threading.Tasks.Task.Factory.StartNew(action, taskCreationOptions); #else - var thread = new System.Threading.Thread(() => action()); - thread.Start(); + new System.Threading.Thread(() => action()) + { + IsBackground = true + }.Start(); #endif } diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs index 0748b8dac..d2bf4bdf1 100644 --- a/src/Renci.SshNet/Session.cs +++ b/src/Renci.SshNet/Session.cs @@ -618,7 +618,8 @@ public void Connect() _messageListenerCompleted.Reset(); // Start incoming request listener - ThreadAbstraction.ExecuteThread(() => MessageListener()); + // ToDo: Make message pump async, to not consume a thread for every session + ThreadAbstraction.ExecuteThreadLongRunning(() => MessageListener()); // Wait for key exchange to be completed WaitOnHandle(_keyExchangeCompletedWaitHandle); From 7bdfc9e615b736b2762f5cd83c31a5f669663ff6 Mon Sep 17 00:00:00 2001 From: Igor Milavec Date: Tue, 14 Dec 2021 21:58:10 +0100 Subject: [PATCH 05/19] Add async support to SftpClient and SftpFileStream (#819) * Add FEATURE_TAP and net472 target * Add TAP async support to SftpClient and SftpFileStream * Add async support to DnsAbstraction and SocketAbstraction * Add async support to *Connector and refactor the hierarchy * Add ConnectAsync to BaseClient --- .../Abstractions/DnsAbstraction.cs | 22 ++ .../Abstractions/SocketAbstraction.cs | 17 + .../Abstractions/SocketExtensions.cs | 119 ++++++ src/Renci.SshNet/BaseClient.cs | 80 ++++ src/Renci.SshNet/Connection/ConnectorBase.cs | 45 +++ .../Connection/DirectConnector.cs | 10 +- src/Renci.SshNet/Connection/HttpConnector.cs | 23 +- src/Renci.SshNet/Connection/IConnector.cs | 5 + .../Connection/IProtocolVersionExchange.cs | 4 + .../Connection/ProtocolVersionExchange.cs | 103 +++++ src/Renci.SshNet/Connection/ProxyConnector.cs | 74 ++++ .../Connection/Socks4Connector.cs | 22 +- .../Connection/Socks5Connector.cs | 22 +- src/Renci.SshNet/ISession.cs | 16 + src/Renci.SshNet/ISftpClient.cs | 89 +++++ src/Renci.SshNet/Renci.SshNet.csproj | 11 +- src/Renci.SshNet/Session.cs | 109 ++++++ src/Renci.SshNet/Sftp/ISftpSession.cs | 47 +++ src/Renci.SshNet/Sftp/SftpFileStream.cs | 355 +++++++++++++++++- src/Renci.SshNet/Sftp/SftpSession.cs | 333 +++++++++++++++- src/Renci.SshNet/SftpClient.cs | 175 +++++++++ 21 files changed, 1611 insertions(+), 70 deletions(-) create mode 100644 src/Renci.SshNet/Abstractions/SocketExtensions.cs create mode 100644 src/Renci.SshNet/Connection/ProxyConnector.cs diff --git a/src/Renci.SshNet/Abstractions/DnsAbstraction.cs b/src/Renci.SshNet/Abstractions/DnsAbstraction.cs index 0af35aeed..a2ac9d58f 100644 --- a/src/Renci.SshNet/Abstractions/DnsAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/DnsAbstraction.cs @@ -2,6 +2,10 @@ using System.Net; using System.Net.Sockets; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif + #if FEATURE_DNS_SYNC #elif FEATURE_DNS_APM using Renci.SshNet.Common; @@ -87,5 +91,23 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress) #endif // FEATURE_DEVICEINFORMATION_APM #endif } + +#if FEATURE_TAP + /// + /// Returns the Internet Protocol (IP) addresses for the specified host. + /// + /// The host name or IP address to resolve + /// + /// A task with result of an array of type that holds the IP addresses for the host that + /// is specified by the parameter. + /// + /// is null. + /// An error is encountered when resolving . + public static Task GetHostAddressesAsync(string hostNameOrAddress) + { + return Dns.GetHostAddressesAsync(hostNameOrAddress); + } +#endif + } } diff --git a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs index 287caea66..2029b0143 100644 --- a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs @@ -3,6 +3,9 @@ using System.Net; using System.Net.Sockets; using System.Threading; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; @@ -59,6 +62,13 @@ public static void Connect(Socket socket, IPEndPoint remoteEndpoint, TimeSpan co ConnectCore(socket, remoteEndpoint, connectTimeout, false); } +#if FEATURE_TAP + public static Task ConnectAsync(Socket socket, IPEndPoint remoteEndpoint, CancellationToken cancellationToken) + { + return socket.ConnectAsync(remoteEndpoint, cancellationToken); + } +#endif + private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSpan connectTimeout, bool ownsSocket) { #if FEATURE_SOCKET_EAP @@ -317,6 +327,13 @@ public static byte[] Read(Socket socket, int size, TimeSpan timeout) return buffer; } +#if FEATURE_TAP + public static Task ReadAsync(Socket socket, byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + return socket.ReceiveAsync(buffer, offset, length, cancellationToken); + } +#endif + /// /// Receives data from a bound into a receive buffer. /// diff --git a/src/Renci.SshNet/Abstractions/SocketExtensions.cs b/src/Renci.SshNet/Abstractions/SocketExtensions.cs new file mode 100644 index 000000000..d763e1a34 --- /dev/null +++ b/src/Renci.SshNet/Abstractions/SocketExtensions.cs @@ -0,0 +1,119 @@ +#if FEATURE_TAP +using System; +using System.Net; +using System.Net.Sockets; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Renci.SshNet.Abstractions +{ + // Async helpers based on https://devblogs.microsoft.com/pfxteam/awaiting-socket-operations/ + + internal static class SocketExtensions + { + sealed class SocketAsyncEventArgsAwaitable : SocketAsyncEventArgs, INotifyCompletion + { + private readonly static Action SENTINEL = () => { }; + + private bool isCancelled; + private Action continuationAction; + + public SocketAsyncEventArgsAwaitable() + { + Completed += delegate { SetCompleted(); }; + } + + public SocketAsyncEventArgsAwaitable ExecuteAsync(Func func) + { + if (!func(this)) + { + SetCompleted(); + } + return this; + } + + public void SetCompleted() + { + IsCompleted = true; + var continuation = continuationAction ?? Interlocked.CompareExchange(ref continuationAction, SENTINEL, null); + if (continuation != null) + { + continuation(); + } + } + + public void SetCancelled() + { + isCancelled = true; + SetCompleted(); + } + + public SocketAsyncEventArgsAwaitable GetAwaiter() { return this; } + + public bool IsCompleted { get; private set; } + + void INotifyCompletion.OnCompleted(Action continuation) + { + if (continuationAction == SENTINEL || Interlocked.CompareExchange(ref continuationAction, continuation, null) == SENTINEL) + { + // We have already completed; run continuation asynchronously + Task.Run(continuation); + } + } + + public void GetResult() + { + if (isCancelled) + { + throw new TaskCanceledException(); + } + else if (IsCompleted) + { + if (SocketError != SocketError.Success) + { + throw new SocketException((int)SocketError); + } + } + else + { + // We don't support sync/async + throw new InvalidOperationException("The asynchronous operation has not yet completed."); + } + } + } + + public static async Task ConnectAsync(this Socket socket, IPEndPoint remoteEndpoint, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + using (var args = new SocketAsyncEventArgsAwaitable()) + { + args.RemoteEndPoint = remoteEndpoint; + + using (cancellationToken.Register(o => ((SocketAsyncEventArgsAwaitable)o).SetCancelled(), args, false)) + { + await args.ExecuteAsync(socket.ConnectAsync); + } + } + } + + public static async Task ReceiveAsync(this Socket socket, byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + using (var args = new SocketAsyncEventArgsAwaitable()) + { + args.SetBuffer(buffer, offset, length); + + using (cancellationToken.Register(o => ((SocketAsyncEventArgsAwaitable)o).SetCancelled(), args, false)) + { + await args.ExecuteAsync(socket.ReceiveAsync); + } + + return args.BytesTransferred; + } + } + } +} +#endif \ No newline at end of file diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index 5b0e01c90..4e0975b09 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -1,6 +1,9 @@ using System; using System.Net.Sockets; using System.Threading; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; @@ -239,6 +242,63 @@ public void Connect() StartKeepAliveTimer(); } +#if FEATURE_TAP + /// + /// Asynchronously connects client to the server. + /// + /// The to observe. + /// A that represents the asynchronous connect operation. + /// + /// The client is already connected. + /// The method was called after the client was disposed. + /// Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname. + /// SSH session could not be established. + /// Authentication of SSH session failed. + /// Failed to establish proxy connection. + public async Task ConnectAsync(CancellationToken cancellationToken) + { + CheckDisposed(); + cancellationToken.ThrowIfCancellationRequested(); + + // TODO (see issue #1758): + // we're not stopping the keep-alive timer and disposing the session here + // + // we could do this but there would still be side effects as concrete + // implementations may still hang on to the original session + // + // therefore it would be better to actually invoke the Disconnect method + // (and then the Dispose on the session) but even that would have side effects + // eg. it would remove all forwarded ports from SshClient + // + // I think we should modify our concrete clients to better deal with a + // disconnect. In case of SshClient this would mean not removing the + // forwarded ports on disconnect (but only on dispose ?) and link a + // forwarded port with a client instead of with a session + // + // To be discussed with Oleg (or whoever is interested) + if (IsSessionConnected()) + throw new InvalidOperationException("The client is already connected."); + + OnConnecting(); + + Session = await CreateAndConnectSessionAsync(cancellationToken).ConfigureAwait(false); + try + { + // Even though the method we invoke makes you believe otherwise, at this point only + // the SSH session itself is connected. + OnConnected(); + } + catch + { + // Only dispose the session as Disconnect() would have side-effects (such as remove forwarded + // ports in SshClient). + DisposeSession(); + throw; + } + StartKeepAliveTimer(); + } +#endif + /// /// Disconnects client from the server. /// @@ -473,6 +533,26 @@ private ISession CreateAndConnectSession() } } +#if FEATURE_TAP + private async Task CreateAndConnectSessionAsync(CancellationToken cancellationToken) + { + var session = _serviceFactory.CreateSession(ConnectionInfo, _serviceFactory.CreateSocketFactory()); + session.HostKeyReceived += Session_HostKeyReceived; + session.ErrorOccured += Session_ErrorOccured; + + try + { + await session.ConnectAsync(cancellationToken).ConfigureAwait(false); + return session; + } + catch + { + DisposeSession(session); + throw; + } + } +#endif + private void DisposeSession(ISession session) { session.ErrorOccured -= Session_ErrorOccured; diff --git a/src/Renci.SshNet/Connection/ConnectorBase.cs b/src/Renci.SshNet/Connection/ConnectorBase.cs index 6e9bed7af..ffa026750 100644 --- a/src/Renci.SshNet/Connection/ConnectorBase.cs +++ b/src/Renci.SshNet/Connection/ConnectorBase.cs @@ -4,6 +4,11 @@ using System; using System.Net; using System.Net.Sockets; +using System.Threading; + +#if FEATURE_TAP +using System.Threading.Tasks; +#endif namespace Renci.SshNet.Connection { @@ -21,6 +26,10 @@ protected ConnectorBase(ISocketFactory socketFactory) public abstract Socket Connect(IConnectionInfo connectionInfo); +#if FEATURE_TAP + public abstract Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken); +#endif + /// /// Establishes a socket connection to the specified host and port. /// @@ -54,6 +63,42 @@ protected Socket SocketConnect(string host, int port, TimeSpan timeout) } } +#if FEATURE_TAP + /// + /// Establishes a socket connection to the specified host and port. + /// + /// The host name of the server to connect to. + /// The port to connect to. + /// The cancellation token to observe. + /// The connection failed to establish within the configured . + /// An error occurred trying to establish the connection. + protected async Task SocketConnectAsync(string host, int port, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var ipAddress = (await DnsAbstraction.GetHostAddressesAsync(host).ConfigureAwait(false))[0]; + var ep = new IPEndPoint(ipAddress, port); + + DiagnosticAbstraction.Log(string.Format("Initiating connection to '{0}:{1}'.", host, port)); + + var socket = SocketFactory.Create(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + try + { + await SocketAbstraction.ConnectAsync(socket, ep, cancellationToken).ConfigureAwait(false); + + const int socketBufferSize = 2 * Session.MaximumSshPacketSize; + socket.SendBufferSize = socketBufferSize; + socket.ReceiveBufferSize = socketBufferSize; + return socket; + } + catch (Exception) + { + socket.Dispose(); + throw; + } + } +#endif + protected static byte SocketReadByte(Socket socket) { var buffer = new byte[1]; diff --git a/src/Renci.SshNet/Connection/DirectConnector.cs b/src/Renci.SshNet/Connection/DirectConnector.cs index ec8464505..0d07bb936 100644 --- a/src/Renci.SshNet/Connection/DirectConnector.cs +++ b/src/Renci.SshNet/Connection/DirectConnector.cs @@ -1,8 +1,9 @@ using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Connection { - internal class DirectConnector : ConnectorBase + internal sealed class DirectConnector : ConnectorBase { public DirectConnector(ISocketFactory socketFactory) : base(socketFactory) { @@ -12,5 +13,12 @@ public override Socket Connect(IConnectionInfo connectionInfo) { return SocketConnect(connectionInfo.Host, connectionInfo.Port, connectionInfo.Timeout); } + +#if FEATURE_TAP + public override System.Threading.Tasks.Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken) + { + return SocketConnectAsync(connectionInfo.Host, connectionInfo.Port, cancellationToken); + } +#endif } } diff --git a/src/Renci.SshNet/Connection/HttpConnector.cs b/src/Renci.SshNet/Connection/HttpConnector.cs index b77f07345..62c4ae279 100644 --- a/src/Renci.SshNet/Connection/HttpConnector.cs +++ b/src/Renci.SshNet/Connection/HttpConnector.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; +using System.Threading; namespace Renci.SshNet.Connection { @@ -27,31 +28,13 @@ namespace Renci.SshNet.Connection /// /// /// - internal class HttpConnector : ConnectorBase + internal sealed class HttpConnector : ProxyConnector { public HttpConnector(ISocketFactory socketFactory) : base(socketFactory) { } - public override Socket Connect(IConnectionInfo connectionInfo) - { - var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout); - - try - { - HandleProxyConnect(connectionInfo, socket); - return socket; - } - catch (Exception) - { - socket.Shutdown(SocketShutdown.Both); - socket.Dispose(); - - throw; - } - } - - private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) + protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) { var httpResponseRe = new Regex(@"HTTP/(?\d[.]\d) (?\d{3}) (?.+)$"); var httpHeaderRe = new Regex(@"(?[^\[\]()<>@,;:\""/?={} \t]+):(?.+)?"); diff --git a/src/Renci.SshNet/Connection/IConnector.cs b/src/Renci.SshNet/Connection/IConnector.cs index 7efc5c5fa..9eccabe62 100644 --- a/src/Renci.SshNet/Connection/IConnector.cs +++ b/src/Renci.SshNet/Connection/IConnector.cs @@ -1,9 +1,14 @@ using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Connection { internal interface IConnector { Socket Connect(IConnectionInfo connectionInfo); + +#if FEATURE_TAP + System.Threading.Tasks.Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken); +#endif } } diff --git a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs index 77bcfbd33..c804c291f 100644 --- a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs +++ b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs @@ -18,5 +18,9 @@ internal interface IProtocolVersionExchange /// The SSH identification of the server. /// SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout); + +#if FEATURE_TAP + System.Threading.Tasks.Task StartAsync(string clientVersion, Socket socket, System.Threading.CancellationToken cancellationToken); +#endif } } diff --git a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs index 1d529a6d1..4e6957c10 100644 --- a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs +++ b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs @@ -7,6 +7,10 @@ using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; +using System.Threading; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif namespace Renci.SshNet.Connection { @@ -78,6 +82,51 @@ public SshIdentification Start(string clientVersion, Socket socket, TimeSpan tim } } +#if FEATURE_TAP + public async Task StartAsync(string clientVersion, Socket socket, CancellationToken cancellationToken) + { + // Immediately send the identification string since the spec states both sides MUST send an identification string + // when the connection has been established + SocketAbstraction.Send(socket, Encoding.UTF8.GetBytes(clientVersion + "\x0D\x0A")); + + var bytesReceived = new List(); + + // Get server version from the server, + // ignore text lines which are sent before if any + while (true) + { + var line = await SocketReadLineAsync(socket, cancellationToken, bytesReceived).ConfigureAwait(false); + if (line == null) + { + if (bytesReceived.Count == 0) + { + throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string.{0}" + + "The connection to the remote server was closed before any data was received.{0}{0}" + + "More information on the Protocol Version Exchange is available here:{0}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + Environment.NewLine), + DisconnectReason.ConnectionLost); + } + + throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string:{0}{0}{1}{0}{0}" + + "More information on the Protocol Version Exchange is available here:{0}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + Environment.NewLine, + PacketDump.Create(bytesReceived, 2)), + DisconnectReason.ProtocolError); + } + + var identificationMatch = ServerVersionRe.Match(line); + if (identificationMatch.Success) + { + return new SshIdentification(GetGroupValue(identificationMatch, "protoversion"), + GetGroupValue(identificationMatch, "softwareversion"), + GetGroupValue(identificationMatch, "comments")); + } + } + } +#endif + private static string GetGroupValue(Match match, string groupName) { var commentsGroup = match.Groups[groupName]; @@ -153,5 +202,59 @@ private static string SocketReadLine(Socket socket, TimeSpan timeout, List return null; } + +#if FEATURE_TAP + private static async Task SocketReadLineAsync(Socket socket, CancellationToken cancellationToken, List buffer) + { + var data = new byte[1]; + + var startPosition = buffer.Count; + + // Read data one byte at a time to find end of line and leave any unhandled information in the buffer + // to be processed by subsequent invocations. + while (true) + { + var bytesRead = await SocketAbstraction.ReadAsync(socket, data, 0, data.Length, cancellationToken).ConfigureAwait(false); + if (bytesRead == 0) + { + throw new SshConnectionException("The connection was closed by the remote host."); + } + + var byteRead = data[0]; + buffer.Add(byteRead); + + // The null character MUST NOT be sent + if (byteRead == Null) + { + throw new SshConnectionException(string.Format(CultureInfo.InvariantCulture, + "The server response contains a null character at position 0x{0:X8}:{1}{1}{2}{1}{1}" + + "A server must not send a null character before the Protocol Version Exchange is complete.{1}{1}" + + "More information is available here:{1}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + buffer.Count, + Environment.NewLine, + PacketDump.Create(buffer.ToArray(), 2))); + } + + if (byteRead == Session.LineFeed) + { + if (buffer.Count > startPosition + 1 && buffer[buffer.Count - 2] == Session.CarriageReturn) + { + // Return current line without CRLF + return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 2)); + } + else + { + // Even though RFC4253 clearly indicates that the identification string should be terminated + // by a CR LF we also support banners and identification strings that are terminated by a LF + + // Return current line without LF + return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 1)); + } + } + } + } +#endif + } } diff --git a/src/Renci.SshNet/Connection/ProxyConnector.cs b/src/Renci.SshNet/Connection/ProxyConnector.cs new file mode 100644 index 000000000..6cc2ac9d4 --- /dev/null +++ b/src/Renci.SshNet/Connection/ProxyConnector.cs @@ -0,0 +1,74 @@ +#if !FEATURE_SOCKET_DISPOSE +using Renci.SshNet.Common; +#endif +using System; +using System.Net.Sockets; +#if FEATURE_TAP +using System.Threading; +using System.Threading.Tasks; +#endif + +namespace Renci.SshNet.Connection +{ + internal abstract class ProxyConnector : ConnectorBase + { + public ProxyConnector(ISocketFactory socketFactory) : + base(socketFactory) + { + } + + protected abstract void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket); + +#if FEATURE_TAP + // ToDo: Performs async/sync fallback, true async version should be implemented in derived classes + protected virtual Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, Socket socket, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + using (cancellationToken.Register(o => ((Socket)o).Dispose(), socket, false)) + { + HandleProxyConnect(connectionInfo, socket); + } + return Task.CompletedTask; + } +#endif + + public override Socket Connect(IConnectionInfo connectionInfo) + { + var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout); + + try + { + HandleProxyConnect(connectionInfo, socket); + return socket; + } + catch (Exception) + { + socket.Shutdown(SocketShutdown.Both); + socket.Dispose(); + + throw; + } + } + +#if FEATURE_TAP + public override async Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken) + { + var socket = await SocketConnectAsync(connectionInfo.ProxyHost, connectionInfo.ProxyPort, cancellationToken).ConfigureAwait(false); + + try + { + await HandleProxyConnectAsync(connectionInfo, socket, cancellationToken).ConfigureAwait(false); + return socket; + } + catch (Exception) + { + socket.Shutdown(SocketShutdown.Both); + socket.Dispose(); + + throw; + } + } +#endif + } +} diff --git a/src/Renci.SshNet/Connection/Socks4Connector.cs b/src/Renci.SshNet/Connection/Socks4Connector.cs index 9154240f8..ccf4e1456 100644 --- a/src/Renci.SshNet/Connection/Socks4Connector.cs +++ b/src/Renci.SshNet/Connection/Socks4Connector.cs @@ -12,36 +12,18 @@ namespace Renci.SshNet.Connection /// /// https://www.openssh.com/txt/socks4.protocol /// - internal class Socks4Connector : ConnectorBase + internal sealed class Socks4Connector : ProxyConnector { public Socks4Connector(ISocketFactory socketFactory) : base(socketFactory) { } - public override Socket Connect(IConnectionInfo connectionInfo) - { - var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout); - - try - { - HandleProxyConnect(connectionInfo, socket); - return socket; - } - catch (Exception) - { - socket.Shutdown(SocketShutdown.Both); - socket.Dispose(); - - throw; - } - } - /// /// Establishes a connection to the server via a SOCKS5 proxy. /// /// The connection information. /// The . - private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) + protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) { var connectionRequest = CreateSocks4ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port, connectionInfo.ProxyUsername); SocketAbstraction.Send(socket, connectionRequest); diff --git a/src/Renci.SshNet/Connection/Socks5Connector.cs b/src/Renci.SshNet/Connection/Socks5Connector.cs index 720ac5004..e1b6859dc 100644 --- a/src/Renci.SshNet/Connection/Socks5Connector.cs +++ b/src/Renci.SshNet/Connection/Socks5Connector.cs @@ -11,36 +11,18 @@ namespace Renci.SshNet.Connection /// /// https://en.wikipedia.org/wiki/SOCKS#SOCKS5 /// - internal class Socks5Connector : ConnectorBase + internal sealed class Socks5Connector : ProxyConnector { public Socks5Connector(ISocketFactory socketFactory) : base(socketFactory) { } - public override Socket Connect(IConnectionInfo connectionInfo) - { - var socket = SocketConnect(connectionInfo.ProxyHost, connectionInfo.ProxyPort, connectionInfo.Timeout); - - try - { - HandleProxyConnect(connectionInfo, socket); - return socket; - } - catch (Exception) - { - socket.Shutdown(SocketShutdown.Both); - socket.Dispose(); - - throw; - } - } - /// /// Establishes a connection to the server via a SOCKS5 proxy. /// /// The connection information. /// The . - private void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) + protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket) { var greeting = new byte[] { diff --git a/src/Renci.SshNet/ISession.cs b/src/Renci.SshNet/ISession.cs index cd950da52..cde647a46 100644 --- a/src/Renci.SshNet/ISession.cs +++ b/src/Renci.SshNet/ISession.cs @@ -6,6 +6,9 @@ using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages.Connection; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif namespace Renci.SshNet { @@ -54,6 +57,19 @@ internal interface ISession : IDisposable /// Failed to establish proxy connection. void Connect(); +#if FEATURE_TAP + /// + /// Asynchronously connects to the server. + /// + /// The to observe. + /// A that represents the asynchronous connect operation. + /// Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname. + /// SSH session could not be established. + /// Authentication of SSH session failed. + /// Failed to establish proxy connection. + Task ConnectAsync(CancellationToken cancellationToken); +#endif + /// /// Create a new SSH session channel. /// diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index 62f432491..dc2d2c899 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -4,6 +4,10 @@ using System.Text; using Renci.SshNet.Sftp; using Renci.SshNet.Common; +#if FEATURE_TAP +using System.Threading; +using System.Threading.Tasks; +#endif namespace Renci.SshNet { @@ -488,6 +492,22 @@ public interface ISftpClient : IDisposable /// The method was called after the client was disposed. void DeleteFile(string path); +#if FEATURE_TAP + /// + /// Asynchronously deletes remote file specified by path. + /// + /// File to be deleted path. + /// The to observe. + /// A that represents the asynchronous delete operation. + /// is null or contains only whitespace characters. + /// Client is not connected. + /// was not found on the remote host. + /// Permission to delete the file was denied by the remote host. -or- A SSH command was denied by the server. + /// A SSH error where is the message from the remote host. + /// The method was called after the client was disposed. + Task DeleteFileAsync(string path, CancellationToken cancellationToken); +#endif + /// /// Downloads remote file specified by the path into the stream. /// @@ -653,6 +673,22 @@ public interface ISftpClient : IDisposable /// The method was called after the client was disposed. SftpFileSytemInformation GetStatus(string path); +#if FEATURE_TAP + /// + /// Asynchronously gets status using statvfs@openssh.com request. + /// + /// The path. + /// The to observe. + /// + /// A that represents the status operation. + /// The task result contains the instance that contains file status information. + /// + /// Client is not connected. + /// is null. + /// The method was called after the client was disposed. + Task GetStatusAsync(string path, CancellationToken cancellationToken); +#endif + /// /// Retrieves list of files in remote directory. /// @@ -668,6 +704,25 @@ public interface ISftpClient : IDisposable /// The method was called after the client was disposed. IEnumerable ListDirectory(string path, Action listCallback = null); +#if FEATURE_TAP + + /// + /// Asynchronously retrieves list of files in remote directory. + /// + /// The path. + /// The to observe. + /// + /// A that represents the asynchronous list operation. + /// The task result contains an enumerable collection of for the files in the directory specified by . + /// + /// is null. + /// Client is not connected. + /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. + /// A SSH error where is the message from the remote host. + /// The method was called after the client was disposed. + Task> ListDirectoryAsync(string path, CancellationToken cancellationToken); +#endif + /// /// Opens a on the specified path with read/write access. /// @@ -695,6 +750,24 @@ public interface ISftpClient : IDisposable /// The method was called after the client was disposed. SftpFileStream Open(string path, FileMode mode, FileAccess access); +#if FEATURE_TAP + /// + /// Asynchronously opens a on the specified path, with the specified mode and access. + /// + /// The file to open. + /// A value that specifies whether a file is created if one does not exist, and determines whether the contents of existing files are retained or overwritten. + /// A value that specifies the operations that can be performed on the file. + /// The to observe. + /// + /// A that represents the asynchronous open operation. + /// The task result contains the that provides access to the specified file, with the specified mode and access. + /// + /// is null. + /// Client is not connected. + /// The method was called after the client was disposed. + Task OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken); +#endif + /// /// Opens an existing file for reading. /// @@ -833,6 +906,22 @@ public interface ISftpClient : IDisposable /// The method was called after the client was disposed. void RenameFile(string oldPath, string newPath); +#if FEATURE_TAP + /// + /// Asynchronously renames remote file from old path to new path. + /// + /// Path to the old file location. + /// Path to the new file location. + /// The to observe. + /// A that represents the asynchronous rename operation. + /// is null. -or- or is null. + /// Client is not connected. + /// Permission to rename the file was denied by the remote host. -or- A SSH command was denied by the server. + /// A SSH error where is the message from the remote host. + /// The method was called after the client was disposed. + Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken); +#endif + /// /// Renames remote file from old path to new path. /// diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index 124ce9d4b..740ec7ee1 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -5,9 +5,9 @@ false Renci.SshNet ../Renci.SshNet.snk - 5 + 6 true - net35;net40;netstandard1.3;netstandard2.0 + net35;net40;net472;netstandard1.3;netstandard2.0 - \ No newline at end of file + From bc99ada7da3f05f50d9379f2644941d91d5bf05a Mon Sep 17 00:00:00 2001 From: Stefan Rinkes Date: Sat, 5 Mar 2022 17:05:02 +0100 Subject: [PATCH 10/19] Agent auth and Keygen (#794) * Allow to set PrivateKeyFile Key directly So you can add your own Key-Classes to SSH.NET * Add ED25519 ctor for just pub key part. * Make ECDSA Key Bits accessible You cant export imported CngKeys. To be able to export them to agent or Key-Files make the private bits also accessible. * Better NETFRAMEWORK vs NETSTANDARD handling * Add Comment Property to Key * Add IPrivateKeySource So Extension can add own PrivateKeyFiles, e.g. PuttyKeyFile. --- src/Renci.SshNet/IPrivateKeySource.cs | 15 ++ src/Renci.SshNet/NetConfClient.cs | 8 +- .../PrivateKeyAuthenticationMethod.cs | 8 +- src/Renci.SshNet/PrivateKeyConnectionInfo.cs | 20 +-- src/Renci.SshNet/PrivateKeyFile.cs | 18 ++- src/Renci.SshNet/ScpClient.cs | 6 +- .../Security/Cryptography/ED25519Key.cs | 9 ++ .../Cryptography/EcdsaDigitalSignature.cs | 12 +- .../Security/Cryptography/EcdsaKey.cs | 131 ++++++++++-------- src/Renci.SshNet/Security/Cryptography/Key.cs | 5 + src/Renci.SshNet/SftpClient.cs | 12 +- src/Renci.SshNet/SshClient.cs | 6 +- 12 files changed, 149 insertions(+), 101 deletions(-) create mode 100644 src/Renci.SshNet/IPrivateKeySource.cs diff --git a/src/Renci.SshNet/IPrivateKeySource.cs b/src/Renci.SshNet/IPrivateKeySource.cs new file mode 100644 index 000000000..fc3405462 --- /dev/null +++ b/src/Renci.SshNet/IPrivateKeySource.cs @@ -0,0 +1,15 @@ +using Renci.SshNet.Security; + +namespace Renci.SshNet +{ + /// + /// Represents private key source interface. + /// + public interface IPrivateKeySource + { + /// + /// Gets the host key. + /// + HostAlgorithm HostKey { get; } + } +} \ No newline at end of file diff --git a/src/Renci.SshNet/NetConfClient.cs b/src/Renci.SshNet/NetConfClient.cs index b1877c601..b7ec82ec2 100644 --- a/src/Renci.SshNet/NetConfClient.cs +++ b/src/Renci.SshNet/NetConfClient.cs @@ -103,7 +103,7 @@ public NetConfClient(string host, string username, string password) /// is invalid, -or- is null or contains only whitespace characters. /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] - public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) + public NetConfClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } @@ -116,7 +116,7 @@ public NetConfClient(string host, int port, string username, params PrivateKeyFi /// Authentication private key file(s) . /// is null. /// is invalid, -or- is null or contains only whitespace characters. - public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles) + public NetConfClient(string host, string username, params IPrivateKeySource[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } @@ -163,7 +163,7 @@ internal NetConfClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, I /// /// The NetConf server capabilities. /// - public XmlDocument ServerCapabilities + public XmlDocument ServerCapabilities { get { return _netConfSession.ServerCapabilities; } } @@ -277,4 +277,4 @@ private INetConfSession CreateAndConnectNetConfSession() } } } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs index 93ebbe19d..43d80b506 100644 --- a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs +++ b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs @@ -28,7 +28,7 @@ public override string Name /// /// Gets the key files used for authentication. /// - public ICollection KeyFiles { get; private set; } + public ICollection KeyFiles { get; private set; } /// /// Initializes a new instance of the class. @@ -36,13 +36,13 @@ public override string Name /// The username. /// The key files. /// is whitespace or null. - public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles) + public PrivateKeyAuthenticationMethod(string username, params IPrivateKeySource[] keyFiles) : base(username) { if (keyFiles == null) throw new ArgumentNullException("keyFiles"); - KeyFiles = new Collection(keyFiles); + KeyFiles = new Collection(keyFiles); } /// @@ -250,4 +250,4 @@ protected override void SaveData() } } } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/PrivateKeyConnectionInfo.cs b/src/Renci.SshNet/PrivateKeyConnectionInfo.cs index 7f0c4f658..1f717631b 100644 --- a/src/Renci.SshNet/PrivateKeyConnectionInfo.cs +++ b/src/Renci.SshNet/PrivateKeyConnectionInfo.cs @@ -15,7 +15,7 @@ public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable /// /// Gets the key files used for authentication. /// - public ICollection KeyFiles { get; private set; } + public ICollection KeyFiles { get; private set; } /// /// Initializes a new instance of the class. @@ -40,7 +40,7 @@ public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyF /// Connection port. /// Connection username. /// Connection key files. - public PrivateKeyConnectionInfo(string host, int port, string username, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles) { } @@ -55,7 +55,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, params P /// The proxy host. /// The proxy port. /// The key files. - public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeySource[] keyFiles) : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty, keyFiles) { } @@ -71,7 +71,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp /// The proxy port. /// The proxy username. /// The key files. - public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeySource[] keyFiles) : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles) { } @@ -85,7 +85,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp /// The proxy host. /// The proxy port. /// The key files. - public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeySource[] keyFiles) : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty, keyFiles) { } @@ -100,7 +100,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy /// The proxy port. /// The proxy username. /// The key files. - public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeySource[] keyFiles) : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles) { } @@ -116,7 +116,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy /// The proxy username. /// The proxy password. /// The key files. - public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeySource[] keyFiles) : this(host, DefaultPort, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, keyFiles) { } @@ -133,10 +133,10 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy /// The proxy username. /// The proxy password. /// The key files. - public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles) + public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params IPrivateKeySource[] keyFiles) : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new PrivateKeyAuthenticationMethod(username, keyFiles)) { - KeyFiles = new Collection(keyFiles); + KeyFiles = new Collection(keyFiles); } #region IDisposable Members @@ -194,4 +194,4 @@ protected virtual void Dispose(bool disposing) #endregion } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index 1424134f6..f29b3e958 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -63,7 +63,7 @@ namespace Renci.SshNet /// /// /// - public class PrivateKeyFile : IDisposable + public class PrivateKeyFile : IPrivateKeySource, IDisposable { private static readonly Regex PrivateKeyRegex = new Regex(@"^-+ *BEGIN (?\w+( \w+)*) PRIVATE KEY *-+\r?\n((Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)|(Comment: ""?[^\r\n]*""?\r?\n))?(?([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k PRIVATE KEY *-+", #if FEATURE_REGEX_COMPILE @@ -79,6 +79,15 @@ public class PrivateKeyFile : IDisposable /// public HostAlgorithm HostKey { get; private set; } + /// + /// Initializes a new instance of the class. + /// + /// The key. + public PrivateKeyFile(Key key) + { + HostKey = new KeyHostAlgorithm(key.ToString(), key); + } + /// /// Initializes a new instance of the class. /// @@ -262,7 +271,7 @@ private void Open(Stream privateKey, string passPhrase) if (decryptedLength > blobSize - 4) throw new SshException("Invalid passphrase."); - + if (keyType == "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}") { var exponent = reader.ReadBigIntWithBits();//e @@ -515,8 +524,7 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) throw new SshException("OpenSSH key type '" + keyType + "' is not supported."); } - //comment, we don't need this but we could log it, not sure if necessary - var comment = privateKeyReader.ReadString(Encoding.UTF8); + parsedKey.Comment = privateKeyReader.ReadString(Encoding.UTF8); //The list of privatekey/comment pairs is padded with the bytes 1, 2, 3, ... //until the total length is a multiple of the cipher block size. @@ -642,4 +650,4 @@ protected override void SaveData() } } } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/ScpClient.cs b/src/Renci.SshNet/ScpClient.cs index 8a252cac9..d8ad55692 100644 --- a/src/Renci.SshNet/ScpClient.cs +++ b/src/Renci.SshNet/ScpClient.cs @@ -142,7 +142,7 @@ public ScpClient(string host, string username, string password) /// is invalid, -or- is null or contains only whitespace characters. /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] - public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) + public ScpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } @@ -155,7 +155,7 @@ public ScpClient(string host, int port, string username, params PrivateKeyFile[] /// Authentication private key file(s) . /// is null. /// is invalid, -or- is null or contains only whitespace characters. - public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles) + public ScpClient(string host, string username, params IPrivateKeySource[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } @@ -466,4 +466,4 @@ private static SshException SecureExecutionRequestRejectedException() throw new SshException("Secure copy execution request was rejected by the server. Please consult the server logs."); } } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs index deb4b1181..15f1cb019 100644 --- a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs @@ -99,6 +99,15 @@ public ED25519Key() { } + /// + /// Initializes a new instance of the class. + /// + /// pk data. + public ED25519Key(byte[] pk) + { + publicKey = pk.TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes); + } + /// /// Initializes a new instance of the class. /// diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs index 38d60966e..920614672 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs @@ -39,12 +39,12 @@ public override bool Verify(byte[] input, byte[] signature) // for 521 sig_size is 132 var sig_size = _key.KeyLength == 521 ? 132 : _key.KeyLength / 4; var ssh_data = new SshDataSignature(signature, sig_size); -#if NETSTANDARD2_0 - return _key.Ecdsa.VerifyData(input, ssh_data.Signature, _key.HashAlgorithm); -#else +#if NETFRAMEWORK var ecdsa = (ECDsaCng)_key.Ecdsa; ecdsa.HashAlgorithm = _key.HashAlgorithm; return ecdsa.VerifyData(input, ssh_data.Signature); +#else + return _key.Ecdsa.VerifyData(input, ssh_data.Signature, _key.HashAlgorithm); #endif } @@ -57,12 +57,12 @@ public override bool Verify(byte[] input, byte[] signature) /// public override byte[] Sign(byte[] input) { -#if NETSTANDARD2_0 - var signed = _key.Ecdsa.SignData(input, _key.HashAlgorithm); -#else +#if NETFRAMEWORK var ecdsa = (ECDsaCng)_key.Ecdsa; ecdsa.HashAlgorithm = _key.HashAlgorithm; var signed = ecdsa.SignData(input); +#else + var signed = _key.Ecdsa.SignData(input, _key.HashAlgorithm); #endif var ssh_data = new SshDataSignature(signed.Length); ssh_data.Signature = signed; diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs index 58861f020..46f1dcc65 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs @@ -18,7 +18,7 @@ public class EcdsaKey : Key, IDisposable internal const string ECDSA_P384_OID_VALUE = "1.3.132.0.34"; // Also called nistP384 or secP384r1 internal const string ECDSA_P521_OID_VALUE = "1.3.132.0.35"; // Also called nistP521or secP521r1 -#if !NETSTANDARD2_0 +#if NETFRAMEWORK internal enum KeyBlobMagicNumber : int { BCRYPT_ECDSA_PUBLIC_P256_MAGIC = 0x31534345, @@ -57,45 +57,45 @@ public override string ToString() return string.Format("ecdsa-sha2-nistp{0}", KeyLength); } -#if NETSTANDARD2_0 +#if NETFRAMEWORK /// /// Gets the HashAlgorithm to use /// - public HashAlgorithmName HashAlgorithm + public CngAlgorithm HashAlgorithm { get { - switch (KeyLength) + switch (Ecdsa.KeySize) { case 256: - return HashAlgorithmName.SHA256; + return CngAlgorithm.Sha256; case 384: - return HashAlgorithmName.SHA384; + return CngAlgorithm.Sha384; case 521: - return HashAlgorithmName.SHA512; + return CngAlgorithm.Sha512; + default: + throw new SshException("Unknown KeySize: " + Ecdsa.KeySize); } - return HashAlgorithmName.SHA256; } } #else /// /// Gets the HashAlgorithm to use /// - public CngAlgorithm HashAlgorithm + public HashAlgorithmName HashAlgorithm { get { - switch (Ecdsa.KeySize) + switch (KeyLength) { case 256: - return CngAlgorithm.Sha256; + return HashAlgorithmName.SHA256; case 384: - return CngAlgorithm.Sha384; + return HashAlgorithmName.SHA384; case 521: - return CngAlgorithm.Sha512; - default: - throw new SshException("Unknown KeySize: " + Ecdsa.KeySize); + return HashAlgorithmName.SHA512; } + return HashAlgorithmName.SHA256; } } #endif @@ -144,28 +144,7 @@ public override BigInteger[] Public byte[] curve; byte[] qx; byte[] qy; -#if NETSTANDARD2_0 - var parameter = Ecdsa.ExportParameters(false); - qx = parameter.Q.X; - qy = parameter.Q.Y; - switch (parameter.Curve.Oid.FriendlyName) - { - case "ECDSA_P256": - case "nistP256": - curve = Encoding.ASCII.GetBytes("nistp256"); - break; - case "ECDSA_P384": - case "nistP384": - curve = Encoding.ASCII.GetBytes("nistp384"); - break; - case "ECDSA_P521": - case "nistP521": - curve = Encoding.ASCII.GetBytes("nistp521"); - break; - default: - throw new SshException("Unexpected Curve Name: " + parameter.Curve.Oid.FriendlyName); - } -#else +#if NETFRAMEWORK var blob = key.Export(CngKeyBlobFormat.EccPublicBlob); KeyBlobMagicNumber magic; @@ -191,6 +170,27 @@ public override BigInteger[] Public default: throw new SshException("Unexpected Curve Magic: " + magic); } +#else + var parameter = Ecdsa.ExportParameters(false); + qx = parameter.Q.X; + qy = parameter.Q.Y; + switch (parameter.Curve.Oid.FriendlyName) + { + case "ECDSA_P256": + case "nistP256": + curve = Encoding.ASCII.GetBytes("nistp256"); + break; + case "ECDSA_P384": + case "nistP384": + curve = Encoding.ASCII.GetBytes("nistp384"); + break; + case "ECDSA_P521": + case "nistP521": + curve = Encoding.ASCII.GetBytes("nistp521"); + break; + default: + throw new SshException("Unexpected Curve Name: " + parameter.Curve.Oid.FriendlyName); + } #endif // Make ECPoint from x and y // Prepend 04 (uncompressed format) + qx-bytes + qy-bytes @@ -212,6 +212,11 @@ public override BigInteger[] Public } } + /// + /// Gets the PrivateKey Bytes + /// + public byte[] PrivateKey { get; private set; } + /// /// Gets ECDsa Object /// @@ -278,29 +283,7 @@ public EcdsaKey(byte[] data) private void Import(string curve_oid, byte[] publickey, byte[] privatekey) { -#if NETSTANDARD2_0 - var curve = ECCurve.CreateFromValue(curve_oid); - var parameter = new ECParameters - { - Curve = curve - }; - - // ECPoint as BigInteger(2) - var cord_size = (publickey.Length - 1) / 2; - var qx = new byte[cord_size]; - Buffer.BlockCopy(publickey, 1, qx, 0, qx.Length); - - var qy = new byte[cord_size]; - Buffer.BlockCopy(publickey, cord_size + 1, qy, 0, qy.Length); - - parameter.Q.X = qx; - parameter.Q.Y = qy; - - if (privatekey != null) - parameter.D = privatekey.TrimLeadingZeros().Pad(cord_size); - - Ecdsa = ECDsa.Create(parameter); -#else +#if NETFRAMEWORK var curve_magic = KeyBlobMagicNumber.BCRYPT_ECDH_PRIVATE_GENERIC_MAGIC; switch (GetCurveName(curve_oid)) { @@ -335,7 +318,10 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) Buffer.BlockCopy(publickey, cord_size + 1, qy, 0, qy.Length); if (privatekey != null) + { privatekey = privatekey.Pad(cord_size); + PrivateKey = privatekey; + } int headerSize = Marshal.SizeOf(typeof(BCRYPT_ECCKEY_BLOB)); int blobSize = headerSize + qx.Length + qy.Length; @@ -355,6 +341,31 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) key = CngKey.Import(blob, privatekey == null ? CngKeyBlobFormat.EccPublicBlob : CngKeyBlobFormat.EccPrivateBlob); Ecdsa = new ECDsaCng(key); +#else + var curve = ECCurve.CreateFromValue(curve_oid); + var parameter = new ECParameters + { + Curve = curve + }; + + // ECPoint as BigInteger(2) + var cord_size = (publickey.Length - 1) / 2; + var qx = new byte[cord_size]; + Buffer.BlockCopy(publickey, 1, qx, 0, qx.Length); + + var qy = new byte[cord_size]; + Buffer.BlockCopy(publickey, cord_size + 1, qy, 0, qy.Length); + + parameter.Q.X = qx; + parameter.Q.Y = qy; + + if (privatekey != null) + { + parameter.D = privatekey.TrimLeadingZeros().Pad(cord_size); + PrivateKey = parameter.D; + } + + Ecdsa = ECDsa.Create(parameter); #endif } diff --git a/src/Renci.SshNet/Security/Cryptography/Key.cs b/src/Renci.SshNet/Security/Cryptography/Key.cs index c668a66c3..61c5150c2 100644 --- a/src/Renci.SshNet/Security/Cryptography/Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/Key.cs @@ -36,6 +36,11 @@ public abstract class Key /// public abstract int KeyLength { get; } + /// + /// Gets the Key Comment + /// + public string Comment { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index 4ac9d5543..d33e21816 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -208,7 +208,7 @@ public SftpClient(string host, string username, string password) /// is invalid. -or- is nunullll or contains only whitespace characters. /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] - public SftpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) + public SftpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } @@ -221,7 +221,7 @@ public SftpClient(string host, int port, string username, params PrivateKeyFile[ /// Authentication private key file(s) . /// is null. /// is invalid. -or- is null or contains only whitespace characters. - public SftpClient(string host, string username, params PrivateKeyFile[] keyFiles) + public SftpClient(string host, string username, params IPrivateKeySource[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } @@ -712,13 +712,13 @@ public bool Exists(string path) // using SSH_FXP_REALPATH is not an alternative as the SFTP specification has not always // been clear on how the server should respond when the specified path is not present on // the server: - // + // // SSH 1 to 4: // No mention of how the server should respond if the path is not present on the server. // // SSH 5: // The server SHOULD fail the request if the path is not present on the server. - // + // // SSH 6: // Draft 06: The server SHOULD fail the request if the path is not present on the server. // Draft 07 to 13: The server MUST NOT fail the request if the path does not exist. @@ -747,7 +747,7 @@ public bool Exists(string path) /// is null or contains only whitespace characters. /// Client is not connected. /// Permission to perform the operation was denied by the remote host. -or- A SSH command was denied by the server. - /// was not found on the remote host./// + /// was not found on the remote host./// /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. /// @@ -2400,4 +2400,4 @@ private ISftpSession CreateAndConnectToSftpSession() } } } -} +} \ No newline at end of file diff --git a/src/Renci.SshNet/SshClient.cs b/src/Renci.SshNet/SshClient.cs index 49c9ff84b..881a173d4 100644 --- a/src/Renci.SshNet/SshClient.cs +++ b/src/Renci.SshNet/SshClient.cs @@ -104,7 +104,7 @@ public SshClient(string host, string username, string password) /// is invalid, -or- is null or contains only whitespace characters. /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] - public SshClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) + public SshClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } @@ -121,7 +121,7 @@ public SshClient(string host, int port, string username, params PrivateKeyFile[] /// /// is null. /// is invalid, -or- is null or contains only whitespace characters. - public SshClient(string host, string username, params PrivateKeyFile[] keyFiles) + public SshClient(string host, string username, params IPrivateKeySource[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } @@ -507,4 +507,4 @@ private void EnsureSessionIsOpen() throw new SshConnectionException("Client not connected."); } } -} +} \ No newline at end of file From 03c6d60736b8f7b42e44d6989a53f9b644a091fb Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 29 May 2022 16:58:07 +0200 Subject: [PATCH 11/19] Use cryptographically secure random number generator. Fixes CVE-2022-29245. --- src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs index 9de7af8fb..1fba1c207 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs @@ -46,9 +46,7 @@ public override void Start(Session session, KeyExchangeInitMessage message) var basepoint = new byte[MontgomeryCurve25519.PublicKeySizeInBytes]; basepoint[0] = 9; - var rnd = new Random(); - _privateKey = new byte[MontgomeryCurve25519.PrivateKeySizeInBytes]; - rnd.NextBytes(_privateKey); + _privateKey = CryptoAbstraction.GenerateRandom(MontgomeryCurve25519.PrivateKeySizeInBytes); _clientExchangeValue = new byte[MontgomeryCurve25519.PublicKeySizeInBytes]; MontgomeryOperations.scalarmult(_clientExchangeValue, 0, _privateKey, 0, basepoint, 0); From bd7c02f6e43e9de77fad745fda9b053605ef9c67 Mon Sep 17 00:00:00 2001 From: drieseng Date: Sun, 29 May 2022 17:00:12 +0200 Subject: [PATCH 12/19] Remove unused import. --- src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs index 1fba1c207..b7a318bb9 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs @@ -1,5 +1,4 @@ -using System; -using Renci.SshNet.Abstractions; +using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; using Renci.SshNet.Security.Chaos.NaCl; From 34ce2bd1d0eb7dc68f8ad5a68f407f66d774f9ed Mon Sep 17 00:00:00 2001 From: Owen Krueger <37021716+Owen-Krueger@users.noreply.github.com> Date: Sun, 3 Jul 2022 14:11:46 -0500 Subject: [PATCH 13/19] Add IBaseClient for BaseClient and ISftpClient to inherit from (#975) Add IBaseClient for BaseClient and ISftpClient to inherit from --- src/Renci.SshNet/BaseClient.cs | 6 +- src/Renci.SshNet/IBaseClient.cs | 108 ++++++++++++++++++++++++++++++++ src/Renci.SshNet/ISftpClient.cs | 4 +- src/Renci.SshNet/SftpClient.cs | 2 +- 4 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/Renci.SshNet/IBaseClient.cs diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index 4e0975b09..754396108 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -13,7 +13,7 @@ namespace Renci.SshNet /// /// Serves as base class for client implementations, provides common client functionality. /// - public abstract class BaseClient : IDisposable + public abstract class BaseClient : IBaseClient, IDisposable { /// /// Holds value indicating whether the connection info is owned by this client. @@ -387,7 +387,7 @@ private void Session_HostKeyReceived(object sender, HostKeyEventArgs e) } } -#region IDisposable Members + #region IDisposable Members private bool _isDisposed; @@ -446,7 +446,7 @@ protected void CheckDisposed() Dispose(false); } -#endregion + #endregion /// /// Stops the keep-alive timer, and waits until all timer callbacks have been diff --git a/src/Renci.SshNet/IBaseClient.cs b/src/Renci.SshNet/IBaseClient.cs new file mode 100644 index 000000000..bd9518ac4 --- /dev/null +++ b/src/Renci.SshNet/IBaseClient.cs @@ -0,0 +1,108 @@ +using Renci.SshNet.Common; +using System; +using System.Net.Sockets; +using System.Threading; +#if FEATURE_TAP +using System.Threading.Tasks; +#endif + +namespace Renci.SshNet +{ + /// + /// Serves as base class for client implementations, provides common client functionality. + /// + public interface IBaseClient + { + /// + /// Gets the connection info. + /// + /// + /// The connection info. + /// + /// The method was called after the client was disposed. + ConnectionInfo ConnectionInfo { get; } + + /// + /// Gets a value indicating whether this client is connected to the server. + /// + /// + /// true if this client is connected; otherwise, false. + /// + /// The method was called after the client was disposed. + bool IsConnected { get; } + + /// + /// Gets or sets the keep-alive interval. + /// + /// + /// The keep-alive interval. Specify negative one (-1) milliseconds to disable the + /// keep-alive. This is the default value. + /// + /// The method was called after the client was disposed. + TimeSpan KeepAliveInterval { get; set; } + + /// + /// Occurs when an error occurred. + /// + /// + /// + /// + event EventHandler ErrorOccurred; + + /// + /// Occurs when host key received. + /// + /// + /// + /// + event EventHandler HostKeyReceived; + + /// + /// Connects client to the server. + /// + /// The client is already connected. + /// The method was called after the client was disposed. + /// Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname. + /// SSH session could not be established. + /// Authentication of SSH session failed. + /// Failed to establish proxy connection. + void Connect(); + +#if FEATURE_TAP + /// + /// Asynchronously connects client to the server. + /// + /// The to observe. + /// A that represents the asynchronous connect operation. + /// + /// The client is already connected. + /// The method was called after the client was disposed. + /// Socket connection to the SSH server or proxy server could not be established, or an error occurred while resolving the hostname. + /// SSH session could not be established. + /// Authentication of SSH session failed. + /// Failed to establish proxy connection. + Task ConnectAsync(CancellationToken cancellationToken); +#endif + + /// + /// Disconnects client from the server. + /// + /// The method was called after the client was disposed. + void Disconnect(); + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + void Dispose(); + + /// + /// Sends a keep-alive message to the server. + /// + /// + /// Use to configure the client to send a keep-alive at regular + /// intervals. + /// + /// The method was called after the client was disposed. + void SendKeepAlive(); + } +} \ No newline at end of file diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index dc2d2c899..eda042eff 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -14,7 +14,7 @@ namespace Renci.SshNet /// /// Implementation of the SSH File Transfer Protocol (SFTP) over SSH. /// - public interface ISftpClient : IDisposable + public interface ISftpClient : IBaseClient, IDisposable { /// /// Gets or sets the maximum size of the buffer in bytes. @@ -720,7 +720,7 @@ public interface ISftpClient : IDisposable /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - Task> ListDirectoryAsync(string path, CancellationToken cancellationToken); + Task> ListDirectoryAsync(string path, CancellationToken cancellationToken); #endif /// diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index d33e21816..a7ce34538 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -552,7 +552,7 @@ public IEnumerable ListDirectory(string path, Action listCallbac /// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server. /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. - public async Task> ListDirectoryAsync(string path, CancellationToken cancellationToken) + public async Task> ListDirectoryAsync(string path, CancellationToken cancellationToken) { base.CheckDisposed(); if (path == null) From b9bc4750ab147948d66678af7e583878ce96f28a Mon Sep 17 00:00:00 2001 From: Masuri Date: Sat, 27 Aug 2022 03:54:30 +0900 Subject: [PATCH 14/19] fix typo (#999) --- src/Renci.SshNet/Sftp/SftpFileReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Renci.SshNet/Sftp/SftpFileReader.cs b/src/Renci.SshNet/Sftp/SftpFileReader.cs index 3aed4f535..a881e9c03 100644 --- a/src/Renci.SshNet/Sftp/SftpFileReader.cs +++ b/src/Renci.SshNet/Sftp/SftpFileReader.cs @@ -82,7 +82,7 @@ public byte[] Read() lock (_readLock) { - // wait until either the next chunk is avalable, an exception has occurred or the current + // wait until either the next chunk is available, an exception has occurred or the current // instance is already disposed while (!_queue.TryGetValue(_nextChunkIndex, out nextChunk) && _exception == null) { From f3ebc290e258d90ba4efd16fd8ab25369330f490 Mon Sep 17 00:00:00 2001 From: LemonPi314 <49930425+LemonPi314@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:33:47 -0500 Subject: [PATCH 15/19] Fix Seek Operations in SftpFileStream (#910) * Fix offset operations in SftpFileStream.Seek * Fix seek exception message and add default case for invalid seek origin * Use named params when throwing ArgumentException * Add tests for seeking from end of file --- ...ningOfStream_OriginEndAndOffsetNegative.cs | 103 ++++++++++++++++++ ...ningOfStream_OriginEndAndOffsetPositive.cs | 103 ++++++++++++++++++ ...eginningOfStream_OriginEndAndOffsetZero.cs | 103 ++++++++++++++++++ src/Renci.SshNet/Sftp/SftpFileStream.cs | 62 ++++------- 4 files changed, 331 insertions(+), 40 deletions(-) create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs create mode 100644 src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs new file mode 100644 index 000000000..e47e716e1 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetNegative : SftpFileStreamTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _length; + private byte[] _handle; + private SftpFileStream _target; + private int _offset; + private SftpFileAttributes _attributes; + private long _actual; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _offset = _random.Next(-_length, -1); + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) + .Returns(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); + } + + protected override void Act() + { + _actual = _target.Seek(_offset, SeekOrigin.End); + } + + [TestMethod] + public void SeekShouldHaveReturnedOffset() + { + Assert.AreEqual(_attributes.Size + _offset, _actual); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() + { + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public void PositionShouldReturnOffset() + { + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + + Assert.AreEqual(_attributes.Size + _offset, _target.Position); + + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs new file mode 100644 index 000000000..506342f1a --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetPositive : SftpFileStreamTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _length; + private byte[] _handle; + private SftpFileStream _target; + private int _offset; + private SftpFileAttributes _attributes; + private long _actual; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _offset = _random.Next(1, int.MaxValue); + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) + .Returns(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); + } + + protected override void Act() + { + _actual = _target.Seek(_offset, SeekOrigin.End); + } + + [TestMethod] + public void SeekShouldHaveReturnedOffset() + { + Assert.AreEqual(_attributes.Size + _offset, _actual); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() + { + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public void PositionShouldReturnOffset() + { + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + + Assert.AreEqual(_attributes.Size + _offset, _target.Position); + + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs new file mode 100644 index 000000000..4791acf85 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Sftp; + +namespace Renci.SshNet.Tests.Classes.Sftp +{ + [TestClass] + public class SftpFileStreamTest_Seek_PositionedAtBeginningOfStream_OriginEndAndOffsetZero : SftpFileStreamTestBase + { + private Random _random; + private string _path; + private FileMode _fileMode; + private FileAccess _fileAccess; + private int _bufferSize; + private uint _readBufferSize; + private uint _writeBufferSize; + private int _length; + private byte[] _handle; + private SftpFileStream _target; + private int _offset; + private SftpFileAttributes _attributes; + private long _actual; + + protected override void SetupData() + { + base.SetupData(); + + _random = new Random(); + _path = _random.Next().ToString(); + _fileMode = FileMode.OpenOrCreate; + _fileAccess = FileAccess.Write; + _bufferSize = _random.Next(5, 1000); + _readBufferSize = (uint)_random.Next(5, 1000); + _writeBufferSize = (uint)_random.Next(5, 1000); + _length = _random.Next(5, 10000); + _handle = GenerateRandom(_random.Next(1, 10), _random); + _offset = 0; + _attributes = SftpFileAttributes.Empty; + } + + protected override void SetupMocks() + { + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestOpen(_path, Flags.Write | Flags.CreateNewOrOpen, false)) + .Returns(_handle); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalReadLength((uint)_bufferSize)) + .Returns(_readBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.CalculateOptimalWriteLength((uint)_bufferSize, _handle)) + .Returns(_writeBufferSize); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.IsOpen) + .Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFSetStat(_handle, _attributes)); + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + SftpSessionMock.InSequence(MockSequence) + .Setup(session => session.RequestFStat(_handle, false)) + .Returns(_attributes); + } + + protected override void Arrange() + { + base.Arrange(); + + _target = new SftpFileStream(SftpSessionMock.Object, _path, _fileMode, _fileAccess, _bufferSize); + _target.SetLength(_length); + } + + protected override void Act() + { + _actual = _target.Seek(_offset, SeekOrigin.End); + } + + [TestMethod] + public void SeekShouldHaveReturnedSize() + { + Assert.AreEqual(_attributes.Size, _actual); + } + + [TestMethod] + public void IsOpenOnSftpSessionShouldHaveBeenInvokedTwice() + { + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(2)); + } + + [TestMethod] + public void PositionShouldReturnSize() + { + SftpSessionMock.InSequence(MockSequence).Setup(session => session.IsOpen).Returns(true); + + Assert.AreEqual(_attributes.Size, _target.Position); + + SftpSessionMock.Verify(session => session.IsOpen, Times.Exactly(3)); + } + } +} diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index ecb424567..b47023687 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -788,26 +788,6 @@ public override long Seek(long offset, SeekOrigin origin) { // Flush the write buffer and then seek. FlushWriteBuffer(); - - switch (origin) - { - case SeekOrigin.Begin: - newPosn = offset; - break; - case SeekOrigin.Current: - newPosn = _position + offset; - break; - case SeekOrigin.End: - var attributes = _session.RequestFStat(_handle, false); - newPosn = attributes.Size - offset; - break; - } - - if (newPosn == -1) - { - throw new EndOfStreamException("End of stream."); - } - _position = newPosn; } else { @@ -838,29 +818,31 @@ public override long Seek(long offset, SeekOrigin origin) // Abandon the read buffer. _bufferPosition = 0; _bufferLen = 0; + } - // Seek to the new position. - switch (origin) - { - case SeekOrigin.Begin: - newPosn = offset; - break; - case SeekOrigin.Current: - newPosn = _position + offset; - break; - case SeekOrigin.End: - var attributes = _session.RequestFStat(_handle, false); - newPosn = attributes.Size - offset; - break; - } - - if (newPosn < 0) - { - throw new EndOfStreamException(); - } + // Seek to the new position. + switch (origin) + { + case SeekOrigin.Begin: + newPosn = offset; + break; + case SeekOrigin.Current: + newPosn = _position + offset; + break; + case SeekOrigin.End: + var attributes = _session.RequestFStat(_handle, false); + newPosn = attributes.Size + offset; + break; + default: + throw new ArgumentException(message: "Invalid seek origin.", paramName: "origin"); + } - _position = newPosn; + if (newPosn < 0) + { + throw new EndOfStreamException(); } + + _position = newPosn; return _position; } } From ab2ccc40bce835ce1d3c136aa702459bfd9948b7 Mon Sep 17 00:00:00 2001 From: Gert Driesen Date: Tue, 20 Dec 2022 16:24:20 +0100 Subject: [PATCH 16/19] Add back copyright to license. (#1060) Fixes #1059. --- LICENSE | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LICENSE b/LICENSE index d13cc4b26..f2aef4f38 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,7 @@ The MIT License (MIT) +Copyright (c) Renci, Oleg Kapeljushnik, Gert Driesen and contributors + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights From cf8510013db0e8a1d54086d67694e041f5ef4b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Nag=C3=B3rski?= Date: Sat, 6 May 2023 22:32:10 +0200 Subject: [PATCH 17/19] Removing old target frameworks (#1109) Remove support for legacy / deprecated target frameworks while adding support for .NET 6.0 (and higher). The supported target frameworks are now: * .NETFramework 4.6.2 (and higher) * .NET Standard 2.0 * .NET 6.0 (and higher) --- README.md | 20 +- appveyor.yml | 12 +- build/build.proj | 115 +- build/nuget/SSH.NET.nuspec | 28 +- build/sandcastle/SSH.NET.shfbproj | 33 +- .../Properties/AssemblyInfo.cs | 5 - .../Renci.SshNet.Silverlight.csproj | 1459 ---------------- src/Renci.SshNet.Silverlight/packages.config | 4 - .../Properties/AssemblyInfo.cs | 5 - .../Renci.SshNet.Silverlight5.csproj | 1463 ---------------- src/Renci.SshNet.Silverlight5/packages.config | 4 - ...nected_KeepAliveInterval_NotNegativeOne.cs | 7 +- .../Classes/ClientAuthenticationTest.cs | 5 +- .../Classes/Common/CountdownEventTest.cs | 49 +- .../Classes/Common/PacketDumpTest.cs | 9 +- .../Common/PipeStream_Close_BlockingWrite.cs | 1 - ...ipeStream_Flush_BytesRemainingAfterRead.cs | 6 +- ...thTest_CreateAbsoluteOrRelativeFilePath.cs | 3 +- .../Classes/Common/SemaphoreLightTest.cs | 15 +- .../Connection/HttpConnectorTestBase.cs | 2 +- ...yClosesConnectionBeforeStatusLineIsSent.cs | 4 + ...nectorTest_Connect_ProxyPasswordIsEmpty.cs | 4 + ...nnectorTest_Connect_ProxyPasswordIsNull.cs | 4 + ...oxyResponseDoesNotContainHttpStatusLine.cs | 4 + ...seStatusIs200_ExtraTextBeforeStatusLine.cs | 4 + ...xyResponseStatusIs200_HeadersAndContent.cs | 4 + ...ct_ProxyResponseStatusIs200_OnlyHeaders.cs | 4 + ...est_Connect_ProxyResponseStatusIsNot200.cs | 4 + ...nectorTest_Connect_ProxyUserNameIsEmpty.cs | 4 + ...nnect_ProxyUserNameIsNotNullAndNotEmpty.cs | 4 + ...nnectorTest_Connect_ProxyUserNameIsNull.cs | 4 + ...rTest_Connect_TimeoutReadingHttpContent.cs | 4 + ...orTest_Connect_TimeoutReadingStatusLine.cs | 4 + ...ectionClosedByServer_NoDataSentByServer.cs | 4 + ...est_ServerResponseContainsNullCharacter.cs | 4 + ...entificationOnlyContainsProtocolVersion.cs | 4 + ...changeTest_ServerResponseValid_Comments.cs | 4 + ...angeTest_ServerResponseValid_NoComments.cs | 4 + ...rminatedByLineFeedWithoutCarriageReturn.cs | 4 + ...Test_TimeoutReadingIdentificationString.cs | 4 + .../Connection/Socks4ConnectorTestBase.cs | 3 +- ...rTest_Connect_ConnectionRejectedByProxy.cs | 4 + ...nnectorTest_Connect_ConnectionSucceeded.cs | 4 + ...onnect_TimeoutReadingDestinationAddress.cs | 4 + ...torTest_Connect_TimeoutReadingReplyCode.cs | 4 + ...Test_Connect_TimeoutReadingReplyVersion.cs | 4 + .../Connection/Socks5ConnectorTestBase.cs | 1 + ...ct_NoAuthentication_ConnectionSucceeded.cs | 4 + ...Connect_ProxySocksVersionIsNotSupported.cs | 4 + ...wordAuthentication_AuthenticationFailed.cs | 4 + ...swordAuthentication_ConnectionSucceeded.cs | 4 + ...entication_PasswordExceedsMaximumLength.cs | 4 + ...entication_UserNameExceedsMaximumLength.cs | 4 + .../Classes/NetConfClientTest.cs | 4 +- ...rectoryInfo_SendExecRequestReturnsFalse.cs | 8 - ...AndFileInfo_SendExecRequestReturnsFalse.cs | 8 - ...thAndStream_SendExecRequestReturnsFalse.cs | 8 - ...InfoAndPath_SendExecRequestReturnsFalse.cs | 8 - ...InfoAndPath_SendExecRequestReturnsFalse.cs | 8 - ...ientTest_Upload_FileInfoAndPath_Success.cs | 8 - ...reamAndPath_SendExecRequestReturnsFalse.cs | 8 - .../SessionTest_Connected_ConnectionReset.cs | 2 +- .../Classes/SftpClientTest.cs | 12 +- .../Common/ArgumentExceptionAssert.cs | 15 + .../Common/AsyncSocketListener.cs | 144 +- .../Renci.SshNet.Tests.csproj | 68 +- .../Properties/AssemblyInfo.cs | 10 - .../Properties/Renci.SshNet.UAP10.rd.xml | 33 - .../Renci.SshNet.UAP10.csproj | 1526 ----------------- src/Renci.SshNet.UAP10/project.json | 18 - src/Renci.SshNet.VS2012.sln | 108 -- src/Renci.SshNet.VS2015.sln | 130 -- src/Renci.SshNet.VS2015.sln.DotSettings | 22 - src/Renci.SshNet.VS2017.sln | 82 - .../Properties/AssemblyInfo.cs | 5 - .../Renci.SshNet.WindowsPhone.csproj | 1435 ---------------- src/Renci.SshNet.WindowsPhone/packages.config | 4 - .../Properties/AssemblyInfo.cs | 8 - .../Renci.SshNet.WindowsPhone8.csproj | 1496 ---------------- .../packages.config | 5 - ...nci.SshNet.VS2019.sln => Renci.SshNet.sln} | 0 .../Abstractions/SocketAbstraction.cs | 4 +- src/Renci.SshNet/ForwardedPortDynamic.NET.cs | 9 + src/Renci.SshNet/Renci.SshNet.csproj | 36 +- .../Renci.SshNet.WindowsPhone8.Tests/App.xaml | 21 - .../App.xaml.cs | 222 --- .../Assets/AlignmentGrid.png | Bin 9042 -> 0 bytes .../Assets/ApplicationIcon.png | Bin 3392 -> 0 bytes .../Assets/Tiles/FlipCycleTileLarge.png | Bin 9930 -> 0 bytes .../Assets/Tiles/FlipCycleTileMedium.png | Bin 9070 -> 0 bytes .../Assets/Tiles/FlipCycleTileSmall.png | Bin 3674 -> 0 bytes .../LocalizedStrings.cs | 14 - .../MainPage.xaml | 62 - .../MainPage.xaml.cs | 21 - .../Properties/AppManifest.xml | 6 - .../Properties/AssemblyInfo.cs | 37 - .../Properties/WMAppManifest.xml | 46 - .../Renci.SshNet.WindowsPhone8.Tests.csproj | 148 -- .../Resources/AppResources.Designer.cs | 108 -- .../Resources/AppResources.resx | 137 -- 100 files changed, 376 insertions(+), 9051 deletions(-) delete mode 100644 src/Renci.SshNet.Silverlight/Properties/AssemblyInfo.cs delete mode 100644 src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj delete mode 100644 src/Renci.SshNet.Silverlight/packages.config delete mode 100644 src/Renci.SshNet.Silverlight5/Properties/AssemblyInfo.cs delete mode 100644 src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj delete mode 100644 src/Renci.SshNet.Silverlight5/packages.config create mode 100644 src/Renci.SshNet.Tests/Common/ArgumentExceptionAssert.cs delete mode 100644 src/Renci.SshNet.UAP10/Properties/AssemblyInfo.cs delete mode 100644 src/Renci.SshNet.UAP10/Properties/Renci.SshNet.UAP10.rd.xml delete mode 100644 src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj delete mode 100644 src/Renci.SshNet.UAP10/project.json delete mode 100644 src/Renci.SshNet.VS2012.sln delete mode 100644 src/Renci.SshNet.VS2015.sln delete mode 100644 src/Renci.SshNet.VS2015.sln.DotSettings delete mode 100644 src/Renci.SshNet.VS2017.sln delete mode 100644 src/Renci.SshNet.WindowsPhone/Properties/AssemblyInfo.cs delete mode 100644 src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj delete mode 100644 src/Renci.SshNet.WindowsPhone/packages.config delete mode 100644 src/Renci.SshNet.WindowsPhone8/Properties/AssemblyInfo.cs delete mode 100644 src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj delete mode 100644 src/Renci.SshNet.WindowsPhone8/packages.config rename src/{Renci.SshNet.VS2019.sln => Renci.SshNet.sln} (100%) delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/App.xaml delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/App.xaml.cs delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Assets/AlignmentGrid.png delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Assets/ApplicationIcon.png delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Assets/Tiles/FlipCycleTileLarge.png delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Assets/Tiles/FlipCycleTileMedium.png delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Assets/Tiles/FlipCycleTileSmall.png delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/LocalizedStrings.cs delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml.cs delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Properties/AppManifest.xml delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Properties/AssemblyInfo.cs delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Properties/WMAppManifest.xml delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Renci.SshNet.WindowsPhone8.Tests.csproj delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.Designer.cs delete mode 100644 test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.resx diff --git a/README.md b/README.md index 242c6dc6a..5708d0af4 100755 --- a/README.md +++ b/README.md @@ -116,15 +116,9 @@ Private keys can be encrypted using one of the following cipher methods: ## Framework Support **SSH.NET** supports the following target frameworks: -* .NET Framework 3.5 -* .NET Framework 4.0 (and higher) -* .NET Standard 1.3 +* .NETFramework 4.6.2 (and higher) * .NET Standard 2.0 -* Silverlight 4 -* Silverlight 5 -* Windows Phone 7.1 -* Windows Phone 8.0 -* Universal Windows Platform 10 +* .NET 6 (and higher) ## Usage @@ -178,16 +172,6 @@ using (var client = new SshClient("sftp.foo.com", "guest", "pwd")) } ``` -## Building SSH.NET - -Software | net35 | net40 | netstandard1.3 | netstandard2.0 | sl4 | sl5 | wp71 | wp8 | uap10.0 | ---------------------------------- | :---: | :---: | :------------: | :------------: | :-: | :-: | :--: | :-: | :-----: | -Windows Phone SDK 8.0 | | | | | x | x | x | x | -Visual Studio 2012 Update 5 | x | x | | | x | x | x | x | -Visual Studio 2015 Update 3 | x | x | | | | x | | x | x -Visual Studio 2017 | x | x | x | x | | | | | -Visual Studio 2019 | x | x | x | x | | | | | - ## Supporting SSH.NET Do you or your company rely on **SSH.NET** in your projects? If you want to encourage us to keep on going and show us that you appreciate our work, please consider becoming a [sponsor](https://github.com/sponsors/sshnet) through GitHub Sponsors. diff --git a/appveyor.yml b/appveyor.yml index 2425ef712..d380a3f58 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,14 +1,14 @@ -os: Visual Studio 2019 +os: Visual Studio 2022 before_build: - - nuget restore src\Renci.SshNet.VS2019.sln + - nuget restore src\Renci.SshNet.sln build: - project: src\Renci.SshNet.VS2019.sln + project: src\Renci.SshNet.sln verbosity: minimal test_script: - cmd: >- - vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net35\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" - - vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net472\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" + vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net462\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" --blame + + vstest.console /logger:Appveyor src\Renci.SshNet.Tests\bin\Debug\net7.0\Renci.SshNet.Tests.dll /TestCaseFilter:"TestCategory!=integration&TestCategory!=LongRunning" --blame \ No newline at end of file diff --git a/build/build.proj b/build/build.proj index 40ef012b6..d2911509c 100644 --- a/build/build.proj +++ b/build/build.proj @@ -8,86 +8,37 @@ MSBuildTasks 1.5.0.214 - - - - $(MSBuildThisFileDirectory)..\src\Renci.SshNet.VS2012.sln - 14.0 - 14.0 - - - $(MSBuildThisFileDirectory)..\src\Renci.SshNet.VS2015.sln - 14.0 - 14.0 - - - - - - $(MSBuildThisFileDirectory)..\src\Renci.SshNet.VS2019.sln - 16.0 - - - - Renci.SshNet.WindowsPhone\bin\$(Configuration) - wp71 - - - Renci.SshNet.WindowsPhone8\bin\$(Configuration) - wp8 - - - Renci.SshNet.Silverlight\bin\$(Configuration) - sl4 - - - Renci.SshNet.Silverlight5\bin\$(Configuration) - sl5 - - - Renci.SshNet.UAP10\bin\$(Configuration) - uap10 - + + $(MSBuildThisFileDirectory)..\src\Renci.SshNet.sln + 17.0 + - - Renci.SshNet\bin\$(Configuration)\net35 - net35 - - - Renci.SshNet\bin\$(Configuration)\net40 - net40 - - - Renci.SshNet\bin\$(Configuration)\netstandard1.3 - netstandard1.3 + + Renci.SshNet\bin\$(Configuration)\net462 + net462 Renci.SshNet\bin\$(Configuration)\netstandard2.0 netstandard2.0 + + Renci.SshNet\bin\$(Configuration)\net6.0 + net6.0 + + + Renci.SshNet\bin\$(Configuration)\net7.0 + net7.0 + - - - - - + - - - - - Configuration=Release;VisualStudioVersion=%(VisualStudioVersionClassic.VisualStudioVersion) - - - - @@ -99,26 +50,11 @@ - - - - - - - - - - - Configuration=Release;VisualStudioVersion=%(VisualStudioVersionClassic.VisualStudioVersion) - - - - - + @@ -131,12 +67,7 @@ - - - - - - + @@ -153,16 +84,6 @@ - - - - - - - - - - diff --git a/build/nuget/SSH.NET.nuspec b/build/nuget/SSH.NET.nuspec index 038305832..3fe48202b 100644 --- a/build/nuget/SSH.NET.nuspec +++ b/build/nuget/SSH.NET.nuspec @@ -16,37 +16,15 @@ en-US ssh scp sftp - - - - - - - - - - - - - + - - - - - - - - - - + - + - diff --git a/build/sandcastle/SSH.NET.shfbproj b/build/sandcastle/SSH.NET.shfbproj index 68579630e..15d8dc2f2 100644 --- a/build/sandcastle/SSH.NET.shfbproj +++ b/build/sandcastle/SSH.NET.shfbproj @@ -1,21 +1,22 @@  - + + v4.6.2 + Debug AnyCPU + 2.0 {f7266fb1-f50a-4a5b-b35a-5ea8ebdc1be9} - 2015.6.5.0 + 2017.9.26.0 Documentation Documentation Documentation - .NET Framework 4.0 + .NET Framework 4.6.2 ..\target\help SshNet.Help en-US @@ -24,25 +25,15 @@ C# Blank False - VS2010 + VS2013 False Guid SSH.NET Client Library Documentation AboveNamespaces - - - - - {@HelpFormatOutputPaths} - - - - - - + - - + + Summary, Parameter, Returns, AutoDocumentCtors, TypeParameter, AutoDocumentDispose OnlyWarningsAndErrors @@ -54,7 +45,7 @@ True + the build. The others are optional common platform types that may appear. --> diff --git a/src/Renci.SshNet.Silverlight/Properties/AssemblyInfo.cs b/src/Renci.SshNet.Silverlight/Properties/AssemblyInfo.cs deleted file mode 100644 index f9c8d3244..000000000 --- a/src/Renci.SshNet.Silverlight/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SSH.NET Silverlight 4")] -[assembly: Guid("2b3f6251-8079-48aa-a76b-df70e40092e2")] \ No newline at end of file diff --git a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj b/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj deleted file mode 100644 index 7505a175a..000000000 --- a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj +++ /dev/null @@ -1,1459 +0,0 @@ - - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {77C294BB-1DC2-49DC-BE16-963F8F22794D} - {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Renci.SshNet - Renci.SshNet - Silverlight - v4.0 - $(TargetFrameworkVersion) - false - true - true - - - - v3.5 - - - true - full - false - Bin\Debug - TRACE;DEBUG;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_MEMORYSTREAM_GETBUFFER - true - true - prompt - 4 - Bin\Debug\Renci.SshNet.xml - - - none - true - Bin\Release - TRACE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_MEMORYSTREAM_GETBUFFER - true - true - prompt - 4 - Bin\Release\Renci.SshNet.xml - 1591 - - - true - - - ..\Renci.SshNet.snk - - - - - ..\..\packages\SshNet.Security.Cryptography.1.2.0\lib\sl4\SshNet.Security.Cryptography.dll - - - - - - - - - Abstractions\CryptoAbstraction.cs - - - Abstractions\DiagnosticAbstraction.cs - - - Abstractions\DnsAbstraction.cs - - - Abstractions\FileSystemAbstraction.cs - - - Abstractions\ReflectionAbstraction.cs - - - Abstractions\SocketAbstraction.cs - - - Abstractions\ThreadAbstraction.cs - - - AuthenticationMethod.cs - - - AuthenticationResult.cs - - - BaseClient.cs - - - Channels\Channel.cs - - - Channels\ChannelDirectTcpip.cs - - - Channels\ChannelForwardedTcpip.cs - - - Channels\ChannelSession.cs - - - Channels\ChannelTypes.cs - - - Channels\ClientChannel.cs - - - Channels\IChannel.cs - - - Channels\IChannelDirectTcpip.cs - - - Channels\IChannelForwardedTcpip.cs - - - Channels\IChannelSession.cs - - - Channels\ServerChannel.cs - - - CipherInfo.cs - - - ClientAuthentication.cs - - - CommandAsyncResult.cs - - - Common\Array.cs - - - Common\ASCIIEncoding.cs - - - Common\AsyncResult.cs - - - Common\AuthenticationBannerEventArgs.cs - - - Common\AuthenticationEventArgs.cs - - - Common\AuthenticationPasswordChangeEventArgs.cs - - - Common\AuthenticationPrompt.cs - - - Common\AuthenticationPromptEventArgs.cs - - - Common\BigInteger.cs - - - Common\ChannelDataEventArgs.cs - - - Common\ChannelEventArgs.cs - - - Common\ChannelExtendedDataEventArgs.cs - - - Common\ChannelOpenConfirmedEventArgs.cs - - - Common\ChannelOpenFailedEventArgs.cs - - - Common\ChannelRequestEventArgs.cs - - - Common\CountdownEvent.cs - - - Common\DerData.cs - - - Common\ExceptionEventArgs.cs - - - Common\Extensions.cs - - - Common\HostKeyEventArgs.cs - - - Common\ObjectIdentifier.cs - - - Common\Pack.cs - - - Common\PacketDump.cs - - - Common\PipeStream.cs - - - Common\PortForwardEventArgs.cs - - - Common\PosixPath.cs - - - Common\ProxyException.cs - - - Common\ScpDownloadEventArgs.cs - - - Common\ScpException.cs - - - Common\ScpUploadEventArgs.cs - - - Common\SemaphoreLight.cs - - - Common\SftpPathNotFoundException.cs - - - Common\SftpPermissionDeniedException.cs - - - Common\ShellDataEventArgs.cs - - - Common\SshAuthenticationException.cs - - - Common\SshConnectionException.cs - - - Common\SshData.cs - - - Common\SshDataStream.cs - - - Common\SshException.cs - - - Common\SshOperationTimeoutException.cs - - - Common\SshPassPhraseNullOrEmptyException.cs - - - Common\TerminalModes.cs - - - Compression\CompressionMode.cs - - - Compression\Compressor.cs - - - Compression\Zlib.cs - - - Compression\ZlibOpenSsh.cs - - - Compression\ZlibStream.cs - - - ConnectionInfo.cs - - - Connection\ConnectorBase.cs - - - Connection\DirectConnector.cs - - - Connection\HttpConnector.cs - - - Connection\IConnector.cs - - - Connection\IProtocolVersionExchange.cs - - - Connection\ISocketFactory.cs - - - Connection\ProtocolVersionExchange.cs - - - Connection\SocketFactory.cs - - - Connection\Socks4Connector.cs - - - Connection\Socks5Connector.cs - - - Connection\SshIdentification.cs - - - ExpectAction.cs - - - ExpectAsyncResult.cs - - - ForwardedPort.cs - - - ForwardedPortDynamic.cs - - - ForwardedPortLocal.cs - - - ForwardedPortRemote.cs - - - ForwardedPortStatus.cs - - - HashInfo.cs - - - IAuthenticationMethod.cs - - - IClientAuthentication.cs - - - IConnectionInfo.cs - - - IForwardedPort.cs - - - IRemotePathTransformation.cs - - - IServiceFactory.cs - - - ISession.cs - - - ISubsystemSession.cs - - - KeyboardInteractiveAuthenticationMethod.cs - - - KeyboardInteractiveConnectionInfo.cs - - - MessageEventArgs.cs - - - Messages\Authentication\BannerMessage.cs - - - Messages\Authentication\FailureMessage.cs - - - Messages\Authentication\InformationRequestMessage.cs - - - Messages\Authentication\InformationResponseMessage.cs - - - Messages\Authentication\PasswordChangeRequiredMessage.cs - - - Messages\Authentication\PublicKeyMessage.cs - - - Messages\Authentication\RequestMessage.cs - - - Messages\Authentication\RequestMessageHost.cs - - - Messages\Authentication\RequestMessageKeyboardInteractive.cs - - - Messages\Authentication\RequestMessageNone.cs - - - Messages\Authentication\RequestMessagePassword.cs - - - Messages\Authentication\RequestMessagePublicKey.cs - - - Messages\Authentication\SuccessMessage.cs - - - Messages\Connection\CancelTcpIpForwardGlobalRequestMessage.cs - - - Messages\Connection\ChannelCloseMessage.cs - - - Messages\Connection\ChannelDataMessage.cs - - - Messages\Connection\ChannelEofMessage.cs - - - Messages\Connection\ChannelExtendedDataMessage.cs - - - Messages\Connection\ChannelFailureMessage.cs - - - Messages\Connection\ChannelMessage.cs - - - Messages\Connection\ChannelOpenConfirmationMessage.cs - - - Messages\Connection\ChannelOpenFailureMessage.cs - - - Messages\Connection\ChannelOpenFailureReasons.cs - - - Messages\Connection\ChannelOpen\ChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\ChannelOpenMessage.cs - - - Messages\Connection\ChannelOpen\DirectTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\ForwardedTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\SessionChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\X11ChannelOpenInfo.cs - - - Messages\Connection\ChannelRequest\BreakRequestInfo.cs - - - Messages\Connection\ChannelRequest\ChannelRequestMessage.cs - - - Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs - - - Messages\Connection\ChannelRequest\EnvironmentVariableRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExecRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitSignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitStatusRequestInfo.cs - - - Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs - - - Messages\Connection\ChannelRequest\PseudoTerminalInfo.cs - - - Messages\Connection\ChannelRequest\RequestInfo.cs - - - Messages\Connection\ChannelRequest\ShellRequestInfo.cs - - - Messages\Connection\ChannelRequest\SignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\SubsystemRequestInfo.cs - - - Messages\Connection\ChannelRequest\WindowChangeRequestInfo.cs - - - Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs - - - Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs - - - Messages\Connection\ChannelSuccessMessage.cs - - - Messages\Connection\ChannelWindowAdjustMessage.cs - - - Messages\Connection\GlobalRequestMessage.cs - - - Messages\Connection\GlobalRequestName.cs - - - Messages\Connection\RequestFailureMessage.cs - - - Messages\Connection\RequestSuccessMessage.cs - - - Messages\Connection\TcpIpForwardGlobalRequestMessage.cs - - - Messages\Message.cs - - - Messages\MessageAttribute.cs - - - Messages\ServiceName.cs - - - Messages\Transport\DebugMessage.cs - - - Messages\Transport\DisconnectMessage.cs - - - Messages\Transport\DisconnectReason.cs - - - Messages\Transport\IgnoreMessage.cs - - - Messages\Transport\IKeyExchangedAllowed.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeGroup.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeInit.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeReply.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs - - - Messages\Transport\KeyExchangeDhInitMessage.cs - - - Messages\Transport\KeyExchangeDhReplyMessage.cs - - - Messages\Transport\KeyExchangeEcdhInitMessage.cs - - - Messages\Transport\KeyExchangeEcdhReplyMessage.cs - - - Messages\Transport\KeyExchangeInitMessage.cs - - - Messages\Transport\NewKeysMessage.cs - - - Messages\Transport\ServiceAcceptMessage.cs - - - Messages\Transport\ServiceRequestMessage.cs - - - Messages\Transport\UnimplementedMessage.cs - - - NoneAuthenticationMethod.cs - - - PasswordAuthenticationMethod.cs - - - PasswordConnectionInfo.cs - - - PrivateKeyAuthenticationMethod.cs - - - PrivateKeyConnectionInfo.cs - - - PrivateKeyFile.cs - - - ProxyTypes.cs - - - RemotePathDoubleQuoteTransformation.cs - - - RemotePathNoneTransformation.cs - - - RemotePathShellQuoteTransformation.cs - - - RemotePathTransformation.cs - - - ScpClient.cs - - - Security\Algorithm.cs - - - Security\Cryptography\BouncyCastle\asn1\sec\SECNamedCurves.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9Curve.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParameters.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParametersHolder.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECPoint.cs - - - Security\Cryptography\BouncyCastle\crypto\agreement\ECDHCBasicAgreement.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricCipherKeyPair.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricKeyParameter.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\GeneralDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\Sha256Digest.cs - - - Security\Cryptography\BouncyCastle\crypto\generators\ECKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IAsymmetricCipherKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\KeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECDomainParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPrivateKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPublicKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\CryptoApiRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\DigestRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\IRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\util\Pack.cs - - - Security\Cryptography\BouncyCastle\math\BigInteger.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\SimpleBigDecimal.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\Tnaf.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\ZTauElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECAlgorithms.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECCurve.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECFieldElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECLookupTable.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPoint.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPointMap.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\ECEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\GlvEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\LongArray.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\AbstractECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointCombMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\GlvMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\IPreCompCallback.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\PreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ValidityPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafL2RMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\field\FiniteFields.cs - - - Security\Cryptography\BouncyCastle\math\field\GenericPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\GF2Polynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\IFiniteField.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\PrimeField.cs - - - Security\Cryptography\BouncyCastle\math\raw\Mod.cs - - - Security\Cryptography\BouncyCastle\math\raw\Nat.cs - - - Security\Cryptography\BouncyCastle\security\DigestUtilities.cs - - - Security\Cryptography\BouncyCastle\security\SecureRandom.cs - - - Security\Cryptography\BouncyCastle\security\SecurityUtilityException.cs - - - Security\Cryptography\BouncyCastle\util\Arrays.cs - - - Security\Cryptography\BouncyCastle\util\BigIntegers.cs - - - Security\Cryptography\BouncyCastle\util\encoders\Hex.cs - - - Security\Cryptography\BouncyCastle\util\encoders\HexEncoder.cs - - - Security\Cryptography\BouncyCastle\util\IMemoable.cs - - - Security\Cryptography\BouncyCastle\util\Integers.cs - - - Security\Cryptography\BouncyCastle\util\MemoableResetException.cs - - - Security\Cryptography\BouncyCastle\util\Times.cs - - - Security\CertificateHostAlgorithm.cs - - - Security\Cryptography\Chaos.NaCl\CryptoBytes.cs - - - Security\Cryptography\Chaos.NaCl\Ed25519.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array16.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array8.cs - - - Security\Cryptography\Chaos.NaCl\Internal\ByteIntegerConverter.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cmov.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cswap.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_invert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnegative.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnonzero.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul121666.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_neg.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_pow22523.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\FieldElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_double_scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_madd.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_msub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p3.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_cached.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_precomp_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_scalarmult_base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\GroupElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\keypair.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\open.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_clamp.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_mul_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_reduce.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sign.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sqrtm1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\InternalAssert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Poly1305Donna.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\Salsa20.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\SalsaCore.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Sha512Internal.cs - - - Security\Cryptography\Chaos.NaCl\MontgomeryCurve25519.cs - - - Security\Cryptography\Chaos.NaCl\Sha512.cs - - - Security\Cryptography\AsymmetricCipher.cs - - - Security\Cryptography\Bcrypt.cs - - - Security\Cryptography\BlockCipher.cs - - - Security\Cryptography\Cipher.cs - - - Security\Cryptography\CipherDigitalSignature.cs - - - Security\Cryptography\Ciphers\AesCipher.cs - - - Security\Cryptography\Ciphers\Arc4Cipher.cs - - - Security\Cryptography\Ciphers\BlowfishCipher.cs - - - Security\Cryptography\Ciphers\CastCipher.cs - - - Security\Cryptography\Ciphers\CipherMode.cs - - - Security\Cryptography\Ciphers\CipherPadding.cs - - - Security\Cryptography\Ciphers\DesCipher.cs - - - Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS5Padding.cs - - - Security\Cryptography\Ciphers\RsaCipher.cs - - - Security\Cryptography\Ciphers\SerpentCipher.cs - - - Security\Cryptography\Ciphers\TripleDesCipher.cs - - - Security\Cryptography\Ciphers\TwofishCipher.cs - - - Security\Cryptography\DigitalSignature.cs - - - Security\Cryptography\DsaDigitalSignature.cs - - - Security\Cryptography\DsaKey.cs - - - Security\Cryptography\ED25519DigitalSignature.cs - - - Security\Cryptography\ED25519Key.cs - - - Security\Cryptography\HMACMD5.cs - - - Security\Cryptography\HMACSHA1.cs - - - Security\Cryptography\HMACSHA256.cs - - - Security\Cryptography\HMACSHA384.cs - - - Security\Cryptography\HMACSHA512.cs - - - Security\Cryptography\Key.cs - - - Security\Cryptography\RsaDigitalSignature.cs - - - Security\Cryptography\RsaKey.cs - - - Security\Cryptography\StreamCipher.cs - - - Security\Cryptography\SymmetricCipher.cs - - - Security\GroupExchangeHashData.cs - - - Security\HostAlgorithm.cs - - - Security\IKeyExchange.cs - - - Security\KeyExchange.cs - - - Security\KeyExchangeDiffieHellman.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha256.cs - - - Security\KeyExchangeDiffieHellmanGroup16Sha512.cs - - - Security\KeyExchangeDiffieHellmanGroup1Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs - - - Security\KeyExchangeDiffieHellmanGroupSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupSha512.cs - - - Security\KeyExchangeDiffieHellmanGroupShaBase.cs - - - Security\KeyExchangeEC.cs - - - Security\KeyExchangeECCurve25519.cs - - - Security\KeyExchangeECDH.cs - - - Security\KeyExchangeECDH256.cs - - - Security\KeyExchangeECDH384.cs - - - Security\KeyExchangeECDH521.cs - - - Security\KeyExchangeHash.cs - - - Security\KeyHostAlgorithm.cs - - - ServiceFactory.cs - - - Session.cs - - - SftpClient.cs - - - ISftpClient.cs - - - Sftp\Flags.cs - - - Sftp\ISftpFileReader.cs - - - Sftp\ISftpResponseFactory.cs - - - Sftp\ISftpSession.cs - - - Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs - - - Sftp\Requests\ExtendedRequests\HardLinkRequest.cs - - - Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs - - - Sftp\Requests\ExtendedRequests\StatVfsRequest.cs - - - Sftp\Requests\SftpBlockRequest.cs - - - Sftp\Requests\SftpCloseRequest.cs - - - Sftp\Requests\SftpExtendedRequest.cs - - - Sftp\Requests\SftpFSetStatRequest.cs - - - Sftp\Requests\SftpFStatRequest.cs - - - Sftp\Requests\SftpInitRequest.cs - - - Sftp\Requests\SftpLinkRequest.cs - - - Sftp\Requests\SftpLStatRequest.cs - - - Sftp\Requests\SftpMkDirRequest.cs - - - Sftp\Requests\SftpOpenDirRequest.cs - - - Sftp\Requests\SftpOpenRequest.cs - - - Sftp\Requests\SftpReadDirRequest.cs - - - Sftp\Requests\SftpReadLinkRequest.cs - - - Sftp\Requests\SftpReadRequest.cs - - - Sftp\Requests\SftpRealPathRequest.cs - - - Sftp\Requests\SftpRemoveRequest.cs - - - Sftp\Requests\SftpRenameRequest.cs - - - Sftp\Requests\SftpRequest.cs - - - Sftp\Requests\SftpRmDirRequest.cs - - - Sftp\Requests\SftpSetStatRequest.cs - - - Sftp\Requests\SftpStatRequest.cs - - - Sftp\Requests\SftpSymLinkRequest.cs - - - Sftp\Requests\SftpUnblockRequest.cs - - - Sftp\Requests\SftpWriteRequest.cs - - - Sftp\Responses\ExtendedReplies\ExtendedReplyInfo.cs - - - Sftp\Responses\ExtendedReplies\StatVfsReplyInfo.cs - - - Sftp\Responses\SftpAttrsResponse.cs - - - Sftp\Responses\SftpDataResponse.cs - - - Sftp\Responses\SftpExtendedReplyResponse.cs - - - Sftp\Responses\SftpHandleResponse.cs - - - Sftp\Responses\SftpNameResponse.cs - - - Sftp\Responses\SftpResponse.cs - - - Sftp\Responses\SftpStatusResponse.cs - - - Sftp\Responses\SftpVersionResponse.cs - - - Sftp\SftpCloseAsyncResult.cs - - - Sftp\SftpDownloadAsyncResult.cs - - - Sftp\SftpFile.cs - - - Sftp\ISftpFile.cs - - - Sftp\SftpFileAttributes.cs - - - Sftp\SftpFileReader.cs - - - Sftp\SftpFileStream.cs - - - Sftp\SftpFileSystemInformation.cs - - - Sftp\SftpListDirectoryAsyncResult.cs - - - Sftp\SftpMessage.cs - - - Sftp\SftpMessageTypes.cs - - - Sftp\SftpOpenAsyncResult.cs - - - Sftp\SftpReadAsyncResult.cs - - - Sftp\SftpRealPathAsyncResult.cs - - - Sftp\SftpResponseFactory.cs - - - Sftp\SftpSession.cs - - - Sftp\SFtpStatAsyncResult.cs - - - Sftp\SftpSynchronizeDirectoriesAsyncResult.cs - - - Sftp\SftpUploadAsyncResult.cs - - - Sftp\StatusCodes.cs - - - Shell.cs - - - ShellStream.cs - - - SshClient.cs - - - SshCommand.cs - - - SshMessageFactory.cs - - - SubsystemSession.cs - - - - Properties\CommonAssemblyInfo.cs - - - - - Renci.SshNet.snk - - - Designer - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.Silverlight/packages.config b/src/Renci.SshNet.Silverlight/packages.config deleted file mode 100644 index c0653dc39..000000000 --- a/src/Renci.SshNet.Silverlight/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.Silverlight5/Properties/AssemblyInfo.cs b/src/Renci.SshNet.Silverlight5/Properties/AssemblyInfo.cs deleted file mode 100644 index 7266e1543..000000000 --- a/src/Renci.SshNet.Silverlight5/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SSH.NET Silverlight 5")] -[assembly: Guid("2b3f6251-8079-48aa-a76b-df70e40092e2")] \ No newline at end of file diff --git a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj b/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj deleted file mode 100644 index cff69e1cd..000000000 --- a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj +++ /dev/null @@ -1,1463 +0,0 @@ - - - - Debug - AnyCPU - 8.0.50727 - 2.0 - {E367F791-C1EC-4181-912A-2943CAC6B3BC} - {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Renci.SshNet - Renci.SshNet - Silverlight - v5.0 - $(TargetFrameworkVersion) - false - true - true - - - - v3.5 - - - true - full - false - Bin\Debug - TRACE;DEBUG;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - false - Bin\Debug\Renci.SshNet.xml - true - - - none - true - Bin\Release - TRACE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - false - Bin\Release\Renci.SshNet.xml - - - true - - - true - - - ..\Renci.SshNet.snk - - - - - ..\..\packages\SshNet.Security.Cryptography.1.2.0\lib\sl5\SshNet.Security.Cryptography.dll - True - - - - - - - - - Abstractions\CryptoAbstraction.cs - - - Abstractions\DiagnosticAbstraction.cs - - - Abstractions\DnsAbstraction.cs - - - Abstractions\FileSystemAbstraction.cs - - - Abstractions\ReflectionAbstraction.cs - - - Abstractions\SocketAbstraction.cs - - - Abstractions\ThreadAbstraction.cs - - - AuthenticationMethod.cs - - - AuthenticationResult.cs - - - BaseClient.cs - - - Channels\Channel.cs - - - Channels\ChannelDirectTcpip.cs - - - Channels\ChannelForwardedTcpip.cs - - - Channels\ChannelSession.cs - - - Channels\ChannelTypes.cs - - - Channels\ClientChannel.cs - - - Channels\IChannel.cs - - - Channels\IChannelDirectTcpip.cs - - - Channels\IChannelForwardedTcpip.cs - - - Channels\IChannelSession.cs - - - Channels\ServerChannel.cs - - - CipherInfo.cs - - - ClientAuthentication.cs - - - CommandAsyncResult.cs - - - Common\Array.cs - - - Common\ASCIIEncoding.cs - - - Common\AsyncResult.cs - - - Common\AuthenticationBannerEventArgs.cs - - - Common\AuthenticationEventArgs.cs - - - Common\AuthenticationPasswordChangeEventArgs.cs - - - Common\AuthenticationPrompt.cs - - - Common\AuthenticationPromptEventArgs.cs - - - Common\BigInteger.cs - - - Common\ChannelDataEventArgs.cs - - - Common\ChannelEventArgs.cs - - - Common\ChannelExtendedDataEventArgs.cs - - - Common\ChannelOpenConfirmedEventArgs.cs - - - Common\ChannelOpenFailedEventArgs.cs - - - Common\ChannelRequestEventArgs.cs - - - Common\CountdownEvent.cs - - - Common\DerData.cs - - - Common\ExceptionEventArgs.cs - - - Common\Extensions.cs - - - Common\HostKeyEventArgs.cs - - - Common\ObjectIdentifier.cs - - - Common\Pack.cs - - - Common\PacketDump.cs - - - Common\PipeStream.cs - - - Common\PortForwardEventArgs.cs - - - Common\PosixPath.cs - - - Common\ProxyException.cs - - - Common\ScpDownloadEventArgs.cs - - - Common\ScpException.cs - - - Common\ScpUploadEventArgs.cs - - - Common\SemaphoreLight.cs - - - Common\SftpPathNotFoundException.cs - - - Common\SftpPermissionDeniedException.cs - - - Common\ShellDataEventArgs.cs - - - Common\SshAuthenticationException.cs - - - Common\SshConnectionException.cs - - - Common\SshData.cs - - - Common\SshDataStream.cs - - - Common\SshException.cs - - - Common\SshOperationTimeoutException.cs - - - Common\SshPassPhraseNullOrEmptyException.cs - - - Common\TerminalModes.cs - - - Compression\CompressionMode.cs - - - Compression\Compressor.cs - - - Compression\Zlib.cs - - - Compression\ZlibOpenSsh.cs - - - Compression\ZlibStream.cs - - - ConnectionInfo.cs - - - Connection\ConnectorBase.cs - - - Connection\DirectConnector.cs - - - Connection\HttpConnector.cs - - - Connection\IConnector.cs - - - Connection\IProtocolVersionExchange.cs - - - Connection\ISocketFactory.cs - - - Connection\ProtocolVersionExchange.cs - - - Connection\SocketFactory.cs - - - Connection\Socks4Connector.cs - - - Connection\Socks5Connector.cs - - - Connection\SshIdentification.cs - - - ExpectAction.cs - - - ExpectAsyncResult.cs - - - ForwardedPort.cs - - - ForwardedPortDynamic.cs - - - ForwardedPortLocal.cs - - - ForwardedPortRemote.cs - - - ForwardedPortStatus.cs - - - HashInfo.cs - - - IAuthenticationMethod.cs - - - IClientAuthentication.cs - - - IConnectionInfo.cs - - - IForwardedPort.cs - - - IRemotePathTransformation.cs - - - IServiceFactory.cs - - - ISession.cs - - - ISubsystemSession.cs - - - KeyboardInteractiveAuthenticationMethod.cs - - - KeyboardInteractiveConnectionInfo.cs - - - MessageEventArgs.cs - - - Messages\Authentication\BannerMessage.cs - - - Messages\Authentication\FailureMessage.cs - - - Messages\Authentication\InformationRequestMessage.cs - - - Messages\Authentication\InformationResponseMessage.cs - - - Messages\Authentication\PasswordChangeRequiredMessage.cs - - - Messages\Authentication\PublicKeyMessage.cs - - - Messages\Authentication\RequestMessage.cs - - - Messages\Authentication\RequestMessageHost.cs - - - Messages\Authentication\RequestMessageKeyboardInteractive.cs - - - Messages\Authentication\RequestMessageNone.cs - - - Messages\Authentication\RequestMessagePassword.cs - - - Messages\Authentication\RequestMessagePublicKey.cs - - - Messages\Authentication\SuccessMessage.cs - - - Messages\Connection\CancelTcpIpForwardGlobalRequestMessage.cs - - - Messages\Connection\ChannelCloseMessage.cs - - - Messages\Connection\ChannelDataMessage.cs - - - Messages\Connection\ChannelEofMessage.cs - - - Messages\Connection\ChannelExtendedDataMessage.cs - - - Messages\Connection\ChannelFailureMessage.cs - - - Messages\Connection\ChannelMessage.cs - - - Messages\Connection\ChannelOpenConfirmationMessage.cs - - - Messages\Connection\ChannelOpenFailureMessage.cs - - - Messages\Connection\ChannelOpenFailureReasons.cs - - - Messages\Connection\ChannelOpen\ChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\ChannelOpenMessage.cs - - - Messages\Connection\ChannelOpen\DirectTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\ForwardedTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\SessionChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\X11ChannelOpenInfo.cs - - - Messages\Connection\ChannelRequest\BreakRequestInfo.cs - - - Messages\Connection\ChannelRequest\ChannelRequestMessage.cs - - - Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs - - - Messages\Connection\ChannelRequest\EnvironmentVariableRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExecRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitSignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitStatusRequestInfo.cs - - - Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs - - - Messages\Connection\ChannelRequest\PseudoTerminalInfo.cs - - - Messages\Connection\ChannelRequest\RequestInfo.cs - - - Messages\Connection\ChannelRequest\ShellRequestInfo.cs - - - Messages\Connection\ChannelRequest\SignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\SubsystemRequestInfo.cs - - - Messages\Connection\ChannelRequest\WindowChangeRequestInfo.cs - - - Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs - - - Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs - - - Messages\Connection\ChannelSuccessMessage.cs - - - Messages\Connection\ChannelWindowAdjustMessage.cs - - - Messages\Connection\GlobalRequestMessage.cs - - - Messages\Connection\GlobalRequestName.cs - - - Messages\Connection\RequestFailureMessage.cs - - - Messages\Connection\RequestSuccessMessage.cs - - - Messages\Connection\TcpIpForwardGlobalRequestMessage.cs - - - Messages\Message.cs - - - Messages\MessageAttribute.cs - - - Messages\ServiceName.cs - - - Messages\Transport\DebugMessage.cs - - - Messages\Transport\DisconnectMessage.cs - - - Messages\Transport\DisconnectReason.cs - - - Messages\Transport\IgnoreMessage.cs - - - Messages\Transport\IKeyExchangedAllowed.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeGroup.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeInit.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeReply.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs - - - Messages\Transport\KeyExchangeDhInitMessage.cs - - - Messages\Transport\KeyExchangeDhReplyMessage.cs - - - Messages\Transport\KeyExchangeEcdhInitMessage.cs - - - Messages\Transport\KeyExchangeEcdhReplyMessage.cs - - - Messages\Transport\KeyExchangeInitMessage.cs - - - Messages\Transport\NewKeysMessage.cs - - - Messages\Transport\ServiceAcceptMessage.cs - - - Messages\Transport\ServiceRequestMessage.cs - - - Messages\Transport\UnimplementedMessage.cs - - - NoneAuthenticationMethod.cs - - - PasswordAuthenticationMethod.cs - - - PasswordConnectionInfo.cs - - - PrivateKeyAuthenticationMethod.cs - - - PrivateKeyConnectionInfo.cs - - - PrivateKeyFile.cs - - - ProxyTypes.cs - - - RemotePathDoubleQuoteTransformation.cs - - - RemotePathNoneTransformation.cs - - - RemotePathShellQuoteTransformation.cs - - - RemotePathTransformation.cs - - - ScpClient.cs - - - Security\Algorithm.cs - - - Security\Cryptography\BouncyCastle\asn1\sec\SECNamedCurves.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9Curve.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParameters.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParametersHolder.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECPoint.cs - - - Security\Cryptography\BouncyCastle\crypto\agreement\ECDHCBasicAgreement.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricCipherKeyPair.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricKeyParameter.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\GeneralDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\Sha256Digest.cs - - - Security\Cryptography\BouncyCastle\crypto\generators\ECKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IAsymmetricCipherKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\KeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECDomainParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPrivateKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPublicKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\CryptoApiRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\DigestRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\IRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\util\Pack.cs - - - Security\Cryptography\BouncyCastle\math\BigInteger.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\SimpleBigDecimal.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\Tnaf.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\ZTauElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECAlgorithms.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECCurve.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECFieldElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECLookupTable.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPoint.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPointMap.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\ECEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\GlvEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\LongArray.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\AbstractECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointCombMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\GlvMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\IPreCompCallback.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\PreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ValidityPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafL2RMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\field\FiniteFields.cs - - - Security\Cryptography\BouncyCastle\math\field\GenericPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\GF2Polynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\IFiniteField.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\PrimeField.cs - - - Security\Cryptography\BouncyCastle\math\raw\Mod.cs - - - Security\Cryptography\BouncyCastle\math\raw\Nat.cs - - - Security\Cryptography\BouncyCastle\security\DigestUtilities.cs - - - Security\Cryptography\BouncyCastle\security\SecureRandom.cs - - - Security\Cryptography\BouncyCastle\security\SecurityUtilityException.cs - - - Security\Cryptography\BouncyCastle\util\Arrays.cs - - - Security\Cryptography\BouncyCastle\util\BigIntegers.cs - - - Security\Cryptography\BouncyCastle\util\encoders\Hex.cs - - - Security\Cryptography\BouncyCastle\util\encoders\HexEncoder.cs - - - Security\Cryptography\BouncyCastle\util\IMemoable.cs - - - Security\Cryptography\BouncyCastle\util\Integers.cs - - - Security\Cryptography\BouncyCastle\util\MemoableResetException.cs - - - Security\Cryptography\BouncyCastle\util\Times.cs - - - Security\CertificateHostAlgorithm.cs - - - Security\Cryptography\Chaos.NaCl\CryptoBytes.cs - - - Security\Cryptography\Chaos.NaCl\Ed25519.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array16.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array8.cs - - - Security\Cryptography\Chaos.NaCl\Internal\ByteIntegerConverter.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cmov.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cswap.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_invert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnegative.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnonzero.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul121666.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_neg.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_pow22523.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\FieldElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_double_scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_madd.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_msub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p3.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_cached.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_precomp_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_scalarmult_base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\GroupElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\keypair.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\open.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_clamp.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_mul_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_reduce.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sign.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sqrtm1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\InternalAssert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Poly1305Donna.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\Salsa20.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\SalsaCore.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Sha512Internal.cs - - - Security\Cryptography\Chaos.NaCl\MontgomeryCurve25519.cs - - - Security\Cryptography\Chaos.NaCl\Sha512.cs - - - Security\Cryptography\AsymmetricCipher.cs - - - Security\Cryptography\Bcrypt.cs - - - Security\Cryptography\BlockCipher.cs - - - Security\Cryptography\Cipher.cs - - - Security\Cryptography\CipherDigitalSignature.cs - - - Security\Cryptography\Ciphers\AesCipher.cs - - - Security\Cryptography\Ciphers\Arc4Cipher.cs - - - Security\Cryptography\Ciphers\BlowfishCipher.cs - - - Security\Cryptography\Ciphers\CastCipher.cs - - - Security\Cryptography\Ciphers\CipherMode.cs - - - Security\Cryptography\Ciphers\CipherPadding.cs - - - Security\Cryptography\Ciphers\DesCipher.cs - - - Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS5Padding.cs - - - Security\Cryptography\Ciphers\RsaCipher.cs - - - Security\Cryptography\Ciphers\SerpentCipher.cs - - - Security\Cryptography\Ciphers\TripleDesCipher.cs - - - Security\Cryptography\Ciphers\TwofishCipher.cs - - - Security\Cryptography\DigitalSignature.cs - - - Security\Cryptography\DsaDigitalSignature.cs - - - Security\Cryptography\DsaKey.cs - - - Security\Cryptography\ED25519DigitalSignature.cs - - - Security\Cryptography\ED25519Key.cs - - - Security\Cryptography\HMACMD5.cs - - - Security\Cryptography\HMACSHA1.cs - - - Security\Cryptography\HMACSHA256.cs - - - Security\Cryptography\HMACSHA384.cs - - - Security\Cryptography\HMACSHA512.cs - - - Security\Cryptography\Key.cs - - - Security\Cryptography\RsaDigitalSignature.cs - - - Security\Cryptography\RsaKey.cs - - - Security\Cryptography\StreamCipher.cs - - - Security\Cryptography\SymmetricCipher.cs - - - Security\GroupExchangeHashData.cs - - - Security\HostAlgorithm.cs - - - Security\IKeyExchange.cs - - - Security\KeyExchange.cs - - - Security\KeyExchangeDiffieHellman.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha256.cs - - - Security\KeyExchangeDiffieHellmanGroup16Sha512.cs - - - Security\KeyExchangeDiffieHellmanGroup1Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs - - - Security\KeyExchangeDiffieHellmanGroupSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupSha512.cs - - - Security\KeyExchangeDiffieHellmanGroupShaBase.cs - - - Security\KeyExchangeEC.cs - - - Security\KeyExchangeECCurve25519.cs - - - Security\KeyExchangeECDH.cs - - - Security\KeyExchangeECDH256.cs - - - Security\KeyExchangeECDH384.cs - - - Security\KeyExchangeECDH521.cs - - - Security\KeyExchangeHash.cs - - - Security\KeyHostAlgorithm.cs - - - ServiceFactory.cs - - - Session.cs - - - SftpClient.cs - - - ISftpClient.cs - - - Sftp\Flags.cs - - - Sftp\ISftpFileReader.cs - - - Sftp\ISftpResponseFactory.cs - - - Sftp\ISftpSession.cs - - - Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs - - - Sftp\Requests\ExtendedRequests\HardLinkRequest.cs - - - Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs - - - Sftp\Requests\ExtendedRequests\StatVfsRequest.cs - - - Sftp\Requests\SftpBlockRequest.cs - - - Sftp\Requests\SftpCloseRequest.cs - - - Sftp\Requests\SftpExtendedRequest.cs - - - Sftp\Requests\SftpFSetStatRequest.cs - - - Sftp\Requests\SftpFStatRequest.cs - - - Sftp\Requests\SftpInitRequest.cs - - - Sftp\Requests\SftpLinkRequest.cs - - - Sftp\Requests\SftpLStatRequest.cs - - - Sftp\Requests\SftpMkDirRequest.cs - - - Sftp\Requests\SftpOpenDirRequest.cs - - - Sftp\Requests\SftpOpenRequest.cs - - - Sftp\Requests\SftpReadDirRequest.cs - - - Sftp\Requests\SftpReadLinkRequest.cs - - - Sftp\Requests\SftpReadRequest.cs - - - Sftp\Requests\SftpRealPathRequest.cs - - - Sftp\Requests\SftpRemoveRequest.cs - - - Sftp\Requests\SftpRenameRequest.cs - - - Sftp\Requests\SftpRequest.cs - - - Sftp\Requests\SftpRmDirRequest.cs - - - Sftp\Requests\SftpSetStatRequest.cs - - - Sftp\Requests\SftpStatRequest.cs - - - Sftp\Requests\SftpSymLinkRequest.cs - - - Sftp\Requests\SftpUnblockRequest.cs - - - Sftp\Requests\SftpWriteRequest.cs - - - Sftp\Responses\ExtendedReplies\ExtendedReplyInfo.cs - - - Sftp\Responses\ExtendedReplies\StatVfsReplyInfo.cs - - - Sftp\Responses\SftpAttrsResponse.cs - - - Sftp\Responses\SftpDataResponse.cs - - - Sftp\Responses\SftpExtendedReplyResponse.cs - - - Sftp\Responses\SftpHandleResponse.cs - - - Sftp\Responses\SftpNameResponse.cs - - - Sftp\Responses\SftpResponse.cs - - - Sftp\Responses\SftpStatusResponse.cs - - - Sftp\Responses\SftpVersionResponse.cs - - - Sftp\SftpCloseAsyncResult.cs - - - Sftp\SftpDownloadAsyncResult.cs - - - Sftp\SftpFile.cs - - - Sftp\ISftpFile.cs - - - Sftp\SftpFileAttributes.cs - - - Sftp\SftpFileReader.cs - - - Sftp\SftpFileStream.cs - - - Sftp\SftpFileSystemInformation.cs - - - Sftp\SftpListDirectoryAsyncResult.cs - - - Sftp\SftpMessage.cs - - - Sftp\SftpMessageTypes.cs - - - Sftp\SftpOpenAsyncResult.cs - - - Sftp\SftpReadAsyncResult.cs - - - Sftp\SftpRealPathAsyncResult.cs - - - Sftp\SftpResponseFactory.cs - - - Sftp\SftpSession.cs - - - Sftp\SFtpStatAsyncResult.cs - - - Sftp\SftpSynchronizeDirectoriesAsyncResult.cs - - - Sftp\SftpUploadAsyncResult.cs - - - Sftp\StatusCodes.cs - - - Shell.cs - - - ShellStream.cs - - - SshClient.cs - - - SshCommand.cs - - - SshMessageFactory.cs - - - SubsystemSession.cs - - - - Properties\CommonAssemblyInfo.cs - - - - - Renci.SshNet.snk - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.Silverlight5/packages.config b/src/Renci.SshNet.Silverlight5/packages.config deleted file mode 100644 index d4c6bef0d..000000000 --- a/src/Renci.SshNet.Silverlight5/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne.cs b/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne.cs index 26a8da00e..b9c50e76d 100644 --- a/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne.cs +++ b/src/Renci.SshNet.Tests/Classes/BaseClientTest_Connected_KeepAliveInterval_NotNegativeOne.cs @@ -56,8 +56,13 @@ protected override void Act() { _client.KeepAliveInterval = _keepAliveInterval; - // allow keep-alive to be sent a few times + // allow keep-alive to be sent a few times. .NET 7 is faster and + // we need to wait less because we want exactly three messages in a session. +#if NETFRAMEWORK Thread.Sleep(195); +#else + Thread.Sleep(180); +#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest.cs b/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest.cs index a5969d354..e2bb4d8c2 100644 --- a/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest.cs +++ b/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest.cs @@ -1,6 +1,7 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; +using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes { @@ -28,7 +29,7 @@ public void Ctor_PartialSuccessLimit_Zero() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); - Assert.AreEqual(string.Format("Cannot be less than one.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message); + ArgumentExceptionAssert.MessageEquals("Cannot be less than one.", ex); Assert.AreEqual("partialSuccessLimit", ex.ParamName); } } @@ -46,7 +47,7 @@ public void Ctor_PartialSuccessLimit_Negative() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); - Assert.AreEqual(string.Format("Cannot be less than one.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message); + ArgumentExceptionAssert.MessageEquals("Cannot be less than one.", ex); Assert.AreEqual("partialSuccessLimit", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs index 742d9e1e1..6954beb14 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; #if !FEATURE_THREAD_COUNTDOWNEVENT @@ -111,16 +112,17 @@ public void Wait_TimeoutInfinite_ShouldBlockUntilCountdownEventIsSet() threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.Wait(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsTrue(actual); Assert.AreEqual(expectedSignalCount, signalCount); Assert.IsTrue(countdownEvent.IsSet); Assert.IsTrue(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= sleep); - Assert.IsTrue(elapsedTime <= sleep.Add(TimeSpan.FromMilliseconds(100))); + Assert.IsTrue(watch.Elapsed >= sleep); + Assert.IsTrue(watch.Elapsed <= sleep.Add(TimeSpan.FromMilliseconds(100))); countdownEvent.Dispose(); } @@ -150,16 +152,17 @@ public void Wait_ShouldReturnTrueWhenCountdownEventIsSetBeforeTimeoutExpires() threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.Wait(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsTrue(actual); Assert.AreEqual(expectedSignalCount, signalCount); Assert.IsTrue(countdownEvent.IsSet); Assert.IsTrue(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= sleep); - Assert.IsTrue(elapsedTime <= timeout); + Assert.IsTrue(watch.Elapsed >= sleep); + Assert.IsTrue(watch.Elapsed <= timeout); countdownEvent.Dispose(); } @@ -189,14 +192,14 @@ public void Wait_ShouldReturnFalseWhenTimeoutExpiresBeforeCountdownEventIsSet() threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.Wait(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsFalse(actual); Assert.IsFalse(countdownEvent.IsSet); Assert.IsFalse(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= timeout); countdownEvent.Wait(Session.InfiniteTimeSpan); countdownEvent.Dispose(); @@ -239,16 +242,17 @@ public void WaitHandle_WaitOne_TimeoutInfinite_ShouldBlockUntilCountdownEventIsS threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.WaitHandle.WaitOne(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsTrue(actual); Assert.AreEqual(expectedSignalCount, signalCount); Assert.IsTrue(countdownEvent.IsSet); Assert.IsTrue(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= sleep); - Assert.IsTrue(elapsedTime <= sleep.Add(TimeSpan.FromMilliseconds(100))); + Assert.IsTrue(watch.Elapsed >= sleep); + Assert.IsTrue(watch.Elapsed <= sleep.Add(TimeSpan.FromMilliseconds(100))); countdownEvent.Dispose(); } @@ -278,16 +282,17 @@ public void WaitHandle_WaitOne_ShouldReturnTrueWhenCountdownEventIsSetBeforeTime threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.Wait(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsTrue(actual); Assert.AreEqual(expectedSignalCount, signalCount); Assert.IsTrue(countdownEvent.IsSet); Assert.IsTrue(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= sleep); - Assert.IsTrue(elapsedTime <= timeout); + Assert.IsTrue(watch.Elapsed >= sleep); + Assert.IsTrue(watch.Elapsed <= timeout); countdownEvent.Dispose(); } @@ -317,14 +322,14 @@ public void WaitHandle_WaitOne_ShouldReturnFalseWhenTimeoutExpiresBeforeCountdow threads[i].Start(); } - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); var actual = countdownEvent.WaitHandle.WaitOne(timeout); - var elapsedTime = DateTime.Now - start; + watch.Stop(); Assert.IsFalse(actual); Assert.IsFalse(countdownEvent.IsSet); Assert.IsFalse(countdownEvent.WaitHandle.WaitOne(0)); - Assert.IsTrue(elapsedTime >= timeout); countdownEvent.Wait(Session.InfiniteTimeSpan); countdownEvent.Dispose(); diff --git a/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs b/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs index 3b481bf46..845f433ba 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/PacketDumpTest.cs @@ -1,6 +1,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Common; using System; +using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Common { @@ -37,11 +38,9 @@ public void Create_ByteArrayAndIndentLevel_IndentLevelLessThanZero() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); -#if NETFRAMEWORK - Assert.AreEqual(string.Format("Cannot be less than zero.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message); -#else - Assert.AreEqual(string.Format("Cannot be less than zero. (Parameter '{1}')", Environment.NewLine, ex.ParamName), ex.Message); -#endif + + ArgumentExceptionAssert.MessageEquals("Cannot be less than zero.", ex); + Assert.AreEqual("indentLevel", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Close_BlockingWrite.cs b/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Close_BlockingWrite.cs index 1fbd2d158..0b6210046 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Close_BlockingWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Close_BlockingWrite.cs @@ -32,7 +32,6 @@ protected override void Arrange() catch (Exception ex) { _writeException = ex; - throw; } }); _writehread.Start(); diff --git a/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Flush_BytesRemainingAfterRead.cs b/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Flush_BytesRemainingAfterRead.cs index 3af0a3dec..95047cac1 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Flush_BytesRemainingAfterRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/PipeStream_Flush_BytesRemainingAfterRead.cs @@ -88,7 +88,7 @@ public void ReadingMoreBytesThanAvailableDoesNotBlock() Assert.AreEqual(0, buffer[2]); Assert.AreEqual(0, buffer[3]); } - +#if NETFRAMEWORK [TestMethod] public void WriteCausesSubsequentReadToBlockUntilRequestedNumberOfBytesAreAvailable() { @@ -104,7 +104,10 @@ public void WriteCausesSubsequentReadToBlockUntilRequestedNumberOfBytesAreAvaila readThread.Start(); Assert.IsFalse(readThread.Join(500)); + + // Thread Abort method is obsolete: https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/thread-abort-obsolete readThread.Abort(); + Assert.AreEqual(int.MaxValue, bytesRead); Assert.AreEqual(0, buffer[0]); @@ -112,5 +115,6 @@ public void WriteCausesSubsequentReadToBlockUntilRequestedNumberOfBytesAreAvaila Assert.AreEqual(0, buffer[2]); Assert.AreEqual(0, buffer[3]); } +#endif } } diff --git a/src/Renci.SshNet.Tests/Classes/Common/PosixPathTest_CreateAbsoluteOrRelativeFilePath.cs b/src/Renci.SshNet.Tests/Classes/Common/PosixPathTest_CreateAbsoluteOrRelativeFilePath.cs index 986ccdea1..7378a30e3 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/PosixPathTest_CreateAbsoluteOrRelativeFilePath.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/PosixPathTest_CreateAbsoluteOrRelativeFilePath.cs @@ -1,6 +1,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Common; using System; +using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Common { @@ -37,7 +38,7 @@ public void Path_Empty() catch (ArgumentException ex) { Assert.IsNull(ex.InnerException); - Assert.AreEqual(string.Format("The path is a zero-length string.{0}Parameter name: {1}", Environment.NewLine, ex.ParamName), ex.Message); + ArgumentExceptionAssert.MessageEquals("The path is a zero-length string.", ex); Assert.AreEqual("path", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/Common/SemaphoreLightTest.cs b/src/Renci.SshNet.Tests/Classes/Common/SemaphoreLightTest.cs index b1d3bfeb0..93322c780 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/SemaphoreLightTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/SemaphoreLightTest.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Common; @@ -58,12 +59,13 @@ public void WaitTest() const int initialCount = 2; var target = new SemaphoreLight(initialCount); - var start = DateTime.Now; + var watch = new Stopwatch(); + watch.Start(); target.Wait(); target.Wait(); - - Assert.IsTrue((DateTime.Now - start).TotalMilliseconds < 50); + + Assert.IsTrue(watch.ElapsedMilliseconds < 50); var releaseThread = new Thread( () => @@ -75,11 +77,10 @@ public void WaitTest() target.Wait(); - var end = DateTime.Now; - var elapsed = end - start; + watch.Stop(); - Assert.IsTrue(elapsed.TotalMilliseconds > 200); - Assert.IsTrue(elapsed.TotalMilliseconds < 250); + Assert.IsTrue(watch.ElapsedMilliseconds > 200); + Assert.IsTrue(watch.ElapsedMilliseconds < 250); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTestBase.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTestBase.cs index 82cfe0c26..1ed56ecd5 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTestBase.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTestBase.cs @@ -24,7 +24,7 @@ protected virtual void SetupData() protected virtual void SetupMocks() { } - + protected sealed override void Arrange() { CreateMocks(); diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent.cs index 72bdca901..cd577ec9c 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent.cs @@ -5,6 +5,7 @@ using System; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -76,6 +77,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsEmpty.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsEmpty.cs index c94933b2c..59fb77aaa 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsEmpty.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsEmpty.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -88,6 +89,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsNull.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsNull.cs index 277a6f292..dd267ef5d 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsNull.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsNull.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -88,6 +89,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(400); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseDoesNotContainHttpStatusLine.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseDoesNotContainHttpStatusLine.cs index b9f90019b..77f9091ad 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseDoesNotContainHttpStatusLine.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseDoesNotContainHttpStatusLine.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -81,6 +82,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_ExtraTextBeforeStatusLine.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_ExtraTextBeforeStatusLine.cs index 704913305..da56fa458 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_ExtraTextBeforeStatusLine.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_ExtraTextBeforeStatusLine.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -92,6 +93,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_HeadersAndContent.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_HeadersAndContent.cs index dc0bba593..e89547b66 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_HeadersAndContent.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_HeadersAndContent.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -92,6 +93,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_OnlyHeaders.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_OnlyHeaders.cs index 235b4dc0a..30cca421e 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_OnlyHeaders.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIs200_OnlyHeaders.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -90,6 +91,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIsNot200.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIsNot200.cs index 9eb0094b7..8edca1811 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIsNot200.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyResponseStatusIsNot200.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -81,6 +82,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsEmpty.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsEmpty.cs index 33c222532..d6b71bd04 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsEmpty.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsEmpty.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -89,6 +90,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNotNullAndNotEmpty.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNotNullAndNotEmpty.cs index dad0e74b5..a12558714 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNotNullAndNotEmpty.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNotNullAndNotEmpty.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -85,6 +86,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNull.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNull.cs index 3de1bddb4..0e11e189b 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNull.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyUserNameIsNull.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -90,6 +91,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingHttpContent.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingHttpContent.cs index b1c24fc62..9c219c016 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingHttpContent.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingHttpContent.cs @@ -10,6 +10,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -113,6 +114,9 @@ protected override void Act() { _stopWatch.Stop(); } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingStatusLine.cs b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingStatusLine.cs index b4d77ec55..a05212312 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingStatusLine.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_TimeoutReadingStatusLine.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -89,6 +90,9 @@ protected override void Act() { _stopWatch.Stop(); } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs index c01aacc10..fea7a6648 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -79,6 +80,9 @@ protected void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseContainsNullCharacter.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseContainsNullCharacter.cs index 29792888e..2b3245eef 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseContainsNullCharacter.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseContainsNullCharacter.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -83,6 +84,9 @@ protected void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseInvalid_SshIdentificationOnlyContainsProtocolVersion.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseInvalid_SshIdentificationOnlyContainsProtocolVersion.cs index ff2bc5e50..b97ba5f8f 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseInvalid_SshIdentificationOnlyContainsProtocolVersion.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseInvalid_SshIdentificationOnlyContainsProtocolVersion.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -84,6 +85,9 @@ protected void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_Comments.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_Comments.cs index df533ebe7..56ad91011 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_Comments.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_Comments.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -76,6 +77,9 @@ protected void Arrange() protected void Act() { _actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_NoComments.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_NoComments.cs index 8b4f5997e..03c1832df 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_NoComments.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_NoComments.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -76,6 +77,9 @@ protected void Arrange() protected void Act() { _actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_TerminatedByLineFeedWithoutCarriageReturn.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_TerminatedByLineFeedWithoutCarriageReturn.cs index 98bbf6fe1..f66afe057 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_TerminatedByLineFeedWithoutCarriageReturn.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ServerResponseValid_TerminatedByLineFeedWithoutCarriageReturn.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -76,6 +77,9 @@ protected void Arrange() protected void Act() { _actual = _protocolVersionExchange.Start(_clientVersion, _client, _timeout); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_TimeoutReadingIdentificationString.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_TimeoutReadingIdentificationString.cs index 6ef1668ff..238d7e337 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_TimeoutReadingIdentificationString.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_TimeoutReadingIdentificationString.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -81,6 +82,9 @@ protected void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTestBase.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTestBase.cs index 50f622561..16dc70006 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTestBase.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTestBase.cs @@ -2,6 +2,7 @@ using Renci.SshNet.Connection; using Renci.SshNet.Tests.Common; using System.Net; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -32,7 +33,7 @@ protected sealed override void Arrange() SetupData(); SetupMocks(); } - + protected ConnectionInfo CreateConnectionInfo(string proxyUser, string proxyPassword) { return new ConnectionInfo(IPAddress.Loopback.ToString(), diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionRejectedByProxy.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionRejectedByProxy.cs index 3ef993f20..e993fa573 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionRejectedByProxy.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionRejectedByProxy.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -81,6 +82,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionSucceeded.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionSucceeded.cs index 9f184942a..f4c97c639 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionSucceeded.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_ConnectionSucceeded.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -92,6 +93,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingDestinationAddress.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingDestinationAddress.cs index df8cc365a..0981e13a9 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingDestinationAddress.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingDestinationAddress.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -93,6 +94,9 @@ protected override void Act() { _stopWatch.Stop(); } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyCode.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyCode.cs index 501ff8fcf..cdcc667ec 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyCode.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyCode.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -89,6 +90,9 @@ protected override void Act() { _stopWatch.Stop(); } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyVersion.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyVersion.cs index 679d213ad..15751c79a 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyVersion.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks4ConnectorTest_Connect_TimeoutReadingReplyVersion.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -81,6 +82,9 @@ protected override void Act() { _stopWatch.Stop(); } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTestBase.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTestBase.cs index 2d2f2cb9b..9125fb34e 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTestBase.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTestBase.cs @@ -4,6 +4,7 @@ using System; using System.Net; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_NoAuthentication_ConnectionSucceeded.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_NoAuthentication_ConnectionSucceeded.cs index 7f4b108ca..61afbf71c 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_NoAuthentication_ConnectionSucceeded.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_NoAuthentication_ConnectionSucceeded.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -122,6 +123,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_ProxySocksVersionIsNotSupported.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_ProxySocksVersionIsNotSupported.cs index dc9a3a9ee..e90bd32c1 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_ProxySocksVersionIsNotSupported.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_ProxySocksVersionIsNotSupported.cs @@ -5,6 +5,7 @@ using System; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -70,6 +71,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_AuthenticationFailed.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_AuthenticationFailed.cs index 878636ba4..a76a100e2 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_AuthenticationFailed.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_AuthenticationFailed.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -97,6 +98,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_ConnectionSucceeded.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_ConnectionSucceeded.cs index b94c40e8b..a9f7e4ef1 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_ConnectionSucceeded.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_ConnectionSucceeded.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Sockets; using System.Text; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -123,6 +124,9 @@ protected override void TearDown() protected override void Act() { _actual = Connector.Connect(_connectionInfo); + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_PasswordExceedsMaximumLength.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_PasswordExceedsMaximumLength.cs index 61db86a4f..5e1d5389b 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_PasswordExceedsMaximumLength.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_PasswordExceedsMaximumLength.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -84,6 +85,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength.cs b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength.cs index 7a0ef5d41..653b41181 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Threading; namespace Renci.SshNet.Tests.Classes.Connection { @@ -84,6 +85,9 @@ protected override void Act() { _actualException = ex; } + + // Give some time to process all messages + Thread.Sleep(200); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/NetConfClientTest.cs b/src/Renci.SshNet.Tests/Classes/NetConfClientTest.cs index d70fea366..0a76674be 100644 --- a/src/Renci.SshNet.Tests/Classes/NetConfClientTest.cs +++ b/src/Renci.SshNet.Tests/Classes/NetConfClientTest.cs @@ -86,7 +86,7 @@ public void OperationTimeout_LessThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); + ArgumentExceptionAssert.MessageEquals("The timeout must represent a value between -1 and Int32.MaxValue, inclusive.", ex); Assert.AreEqual("value", ex.ParamName); } } @@ -105,7 +105,7 @@ public void OperationTimeout_GreaterThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); + ArgumentExceptionAssert.MessageEquals("The timeout must represent a value between -1 and Int32.MaxValue, inclusive.", ex); Assert.AreEqual("value", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs index dd7e61e61..620f3dd29 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs @@ -54,11 +54,7 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -106,11 +102,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs index 8d1d1a1a2..f0ea9758a 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs @@ -53,11 +53,7 @@ protected override void SetupMocks() _channelSessionMock.InSequence(sequence) .Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath))).Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -105,11 +101,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs index 0fe2566fa..bbb025209 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs @@ -54,11 +54,7 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -116,11 +112,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs index 5c8d7c282..f2521136a 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs @@ -53,11 +53,7 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -r -p -d -t {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -105,11 +101,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs index 57d89d698..782ffe977 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs @@ -59,11 +59,7 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -122,11 +118,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs index 3cae19e67..6e31f4e2a 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_Success.cs @@ -84,11 +84,7 @@ protected override void SetupMocks() p => p.SendData(It.Is(b => b.SequenceEqual(new byte[] {0})))); _pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -134,11 +130,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs index 21c761134..f253a8da2 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs @@ -57,11 +57,7 @@ protected override void SetupMocks() .Setup(p => p.SendExecRequest(string.Format("scp -t -d {0}", _transformedPath))) .Returns(false); _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); -#if NET35 - _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); -#else _pipeStreamMock.InSequence(sequence).Setup(p => p.Close()); -#endif } protected override void Arrange() @@ -119,11 +115,7 @@ public void DisposeOnChannelShouldBeInvokedOnce() [TestMethod] public void DisposeOnPipeStreamShouldBeInvokedOnce() { -#if NET35 - _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); -#else _pipeStreamMock.Verify(p => p.Close(), Times.Once); -#endif } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs b/src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs index a177317f3..f17209beb 100644 --- a/src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs +++ b/src/Renci.SshNet.Tests/Classes/SessionTest_Connected_ConnectionReset.cs @@ -17,7 +17,7 @@ protected override void Act() ServerSocket.Close(); // give session some time to react to connection reset - Thread.Sleep(200); + Thread.Sleep(300); } [TestMethod] diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs index 506891910..a66e49312 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs @@ -94,11 +94,7 @@ public void OperationTimeout_LessThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); -#if NETFRAMEWORK - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); -#else - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive. (Parameter '" + ex.ParamName + "')", ex.Message); -#endif + ArgumentExceptionAssert.MessageEquals("The timeout must represent a value between -1 and Int32.MaxValue, inclusive.", ex); Assert.AreEqual("value", ex.ParamName); } } @@ -117,11 +113,7 @@ public void OperationTimeout_GreaterThanLowerLimit() catch (ArgumentOutOfRangeException ex) { Assert.IsNull(ex.InnerException); -#if NETFRAMEWORK - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive." + Environment.NewLine + "Parameter name: " + ex.ParamName, ex.Message); -#else - Assert.AreEqual("The timeout must represent a value between -1 and Int32.MaxValue, inclusive. (Parameter '" + ex.ParamName + "')", ex.Message); -#endif + ArgumentExceptionAssert.MessageEquals("The timeout must represent a value between -1 and Int32.MaxValue, inclusive.", ex); Assert.AreEqual("value", ex.ParamName); } } diff --git a/src/Renci.SshNet.Tests/Common/ArgumentExceptionAssert.cs b/src/Renci.SshNet.Tests/Common/ArgumentExceptionAssert.cs new file mode 100644 index 000000000..5caee457d --- /dev/null +++ b/src/Renci.SshNet.Tests/Common/ArgumentExceptionAssert.cs @@ -0,0 +1,15 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Renci.SshNet.Tests.Common +{ + public static class ArgumentExceptionAssert + { + public static void MessageEquals(string expected, ArgumentException exception) + { + var newMessage = new ArgumentException(expected, exception.ParamName); + + Assert.AreEqual(newMessage.Message, exception.Message); + } + } +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs index 5512b15c7..8fa81a301 100644 --- a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs +++ b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs @@ -107,12 +107,24 @@ public void Dispose() private void StartListener(object state) { - var listener = (Socket)state; - while (_started) + try { - _acceptCallbackDone.Reset(); - listener.BeginAccept(AcceptCallback, listener); - _acceptCallbackDone.WaitOne(); + var listener = (Socket)state; + while (_started) + { + _acceptCallbackDone.Reset(); + listener.BeginAccept(AcceptCallback, listener); + _acceptCallbackDone.WaitOne(); + } + } + catch (Exception ex) + { + // On .NET framework when Thread throws an exception then unit tests + // were executed without any problem. + // On new .NET exceptions from Thread breaks unit tests session. + Console.Error.WriteLine("[{0}] Failure in StartListener: {1}", + typeof(AsyncSocketListener).FullName, + ex); } } @@ -131,21 +143,38 @@ private void AcceptCallback(IAsyncResult ar) { handler = listener.EndAccept(ar); } + catch (SocketException ex) + { + // The listener is stopped through a Dispose() call, which in turn causes + // Socket.EndAccept(...) to throw a SocketException or + // ObjectDisposedException + // + // Since we consider such an exception normal when the listener is being + // stopped, we only write a message to stderr if the listener is considered + // to be up and running + if (_started) + { + Console.Error.WriteLine("[{0}] Failure accepting new connection: {1}", + typeof(AsyncSocketListener).FullName, + ex); + } + return; + } catch (ObjectDisposedException ex) { // The listener is stopped through a Dispose() call, which in turn causes - // Socket.EndAccept(IAsyncResult) to throw an ObjectDisposedException + // Socket.EndAccept(IAsyncResult) to throw a SocketException or + // ObjectDisposedException // - // Since we consider this ObjectDisposedException normal when the listener - // is being stopped, we only write a message to stderr if the listener - // is considered to be up and running + // Since we consider such an exception normal when the listener is being + // stopped, we only write a message to stderr if the listener is considered + // to be up and running if (_started) { Console.Error.WriteLine("[{0}] Failure accepting new connection: {1}", - typeof(AsyncSocketListener).FullName, - ex); + typeof(AsyncSocketListener).FullName, + ex); } - return; } @@ -164,14 +193,31 @@ private void AcceptCallback(IAsyncResult ar) { handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state); } + catch (SocketException ex) + { + // The listener is stopped through a Dispose() call, which in turn causes + // Socket.BeginReceive(...) to throw a SocketException or + // ObjectDisposedException + // + // Since we consider such an exception normal when the listener is being + // stopped, we only write a message to stderr if the listener is considered + // to be up and running + if (_started) + { + Console.Error.WriteLine("[{0}] Failure receiving new data: {1}", + typeof(AsyncSocketListener).FullName, + ex); + } + } catch (ObjectDisposedException ex) { // The listener is stopped through a Dispose() call, which in turn causes - // Socket.BeginReceive(...) to throw an ObjectDisposedException + // Socket.BeginReceive(...) to throw a SocketException or + // ObjectDisposedException // - // Since we consider this ObjectDisposedException normal when the listener - // is being stopped, we only write a message to stderr if the listener - // is considered to be up and running + // Since we consider such an exception normal when the listener is being + // stopped, we only write a message to stderr if the listener is considered + // to be up and running if (_started) { Console.Error.WriteLine("[{0}] Failure receiving new data: {1}", @@ -192,7 +238,11 @@ private void ReadCallback(IAsyncResult ar) try { // Read data from the client socket. - bytesRead = handler.EndReceive(ar); + bytesRead = handler.EndReceive(ar, out var errorCode); + if (errorCode != SocketError.Success) + { + bytesRead = 0; + } } catch (SocketException ex) { @@ -229,28 +279,7 @@ private void ReadCallback(IAsyncResult ar) return; } - if (bytesRead > 0) - { - var bytesReceived = new byte[bytesRead]; - Array.Copy(state.Buffer, bytesReceived, bytesRead); - SignalBytesReceived(bytesReceived, handler); - - try - { - handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state); - } - catch (SocketException ex) - { - if (!_started) - { - throw new Exception("BeginReceive while stopping!", ex); - } - - throw new Exception("BeginReceive while started!: " + ex.SocketErrorCode + " " + _stackTrace, ex); - } - - } - else + void ConnectionDisconnected() { SignalDisconnected(handler); @@ -262,11 +291,17 @@ private void ReadCallback(IAsyncResult ar) { return; } + try { handler.Shutdown(SocketShutdown.Send); handler.Close(); } + catch (SocketException ex) when (ex.SocketErrorCode == SocketError.ConnectionReset) + { + // On .NET 7 we got Socker Exception with ConnectionReset from Shutdown method + // when the socket is disposed + } catch (SocketException ex) { throw new Exception("Exception in ReadCallback: " + ex.SocketErrorCode + " " + _stackTrace, ex); @@ -280,6 +315,37 @@ private void ReadCallback(IAsyncResult ar) } } } + + if (bytesRead > 0) + { + var bytesReceived = new byte[bytesRead]; + Array.Copy(state.Buffer, bytesReceived, bytesRead); + SignalBytesReceived(bytesReceived, handler); + + try + { + handler.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, ReadCallback, state); + } + catch (ObjectDisposedException) + { + // TODO On .NET 7, sometimes we get ObjectDisposedException when _started but only on appveyor, locally it works + ConnectionDisconnected(); + } + catch (SocketException ex) + { + if (!_started) + { + throw new Exception("BeginReceive while stopping!", ex); + } + + throw new Exception("BeginReceive while started!: " + ex.SocketErrorCode + " " + _stackTrace, ex); + } + + } + else + { + ConnectionDisconnected(); + } } private void SignalBytesReceived(byte[] bytesReceived, Socket client) diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index 3b38bfbe8..b577179e2 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -1,44 +1,15 @@  - 7.3 - true + 7.3 + true ..\Renci.SshNet.snk + net462;net6.0;net7.0 - - net35;net472;netcoreapp2.1 - - - net35;net472;netcoreapp3.1;net5.0 - - - net472;netcoreapp3.1;net5.0;net6.0 - - - - - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP - - + FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP + @@ -73,18 +44,6 @@ - - - $(MSBuildProgramFiles32)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - $(MSTestV1UnitTestFrameworkAssemblyCandidate) - - $(MSBuildProgramFiles32)\Microsoft Visual Studio\2017\Professional\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - $(MSTestV1UnitTestFrameworkAssemblyCandidate) - - $(MSBuildProgramFiles32)\Microsoft Visual Studio\2017\Community\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll - $(MSTestV1UnitTestFrameworkAssemblyCandidate) - - $(MSBuildProgramFiles32)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll @@ -100,17 +59,12 @@ $(MSTestV1UnitTestFrameworkAssemblyCandidate) - - - $(MSTestV1UnitTestFrameworkAssembly) - - - - - - - - + + + + + + diff --git a/src/Renci.SshNet.UAP10/Properties/AssemblyInfo.cs b/src/Renci.SshNet.UAP10/Properties/AssemblyInfo.cs deleted file mode 100644 index f71ba6793..000000000 --- a/src/Renci.SshNet.UAP10/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; - -[assembly: AssemblyTitle("SSH.NET UAP 10.0")] -[assembly: InternalsVisibleTo("Renci.SshNet.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f9194e1eb66b7e2575aaee115ee1d27bc100920e7150e43992d6f668f9737de8b9c7ae892b62b8a36dd1d57929ff1541665d101dc476d6e02390846efae7e5186eec409710fdb596e3f83740afef0d4443055937649bc5a773175b61c57615dac0f0fd10f52b52fedf76c17474cc567b3f7a79de95dde842509fb39aaf69c6c2")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] - -// https://github.com/dotnet/corefx/issues/7274 -//[assembly: Guid("4EE4F2DC-208D-42B2-B286-5E5DEC1DD766")] \ No newline at end of file diff --git a/src/Renci.SshNet.UAP10/Properties/Renci.SshNet.UAP10.rd.xml b/src/Renci.SshNet.UAP10/Properties/Renci.SshNet.UAP10.rd.xml deleted file mode 100644 index ba5e1b0ac..000000000 --- a/src/Renci.SshNet.UAP10/Properties/Renci.SshNet.UAP10.rd.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj b/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj deleted file mode 100644 index a1f0c994f..000000000 --- a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj +++ /dev/null @@ -1,1526 +0,0 @@ - - - - - Debug - AnyCPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80} - Library - Properties - Renci.SshNet - Renci.SshNet - en-US - UAP - 10.0.10240.0 - 10.0.10240.0 - 14 - 512 - {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - - - AnyCPU - true - full - false - bin\Debug\ - TRACE;DEBUG;FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - prompt - 4 - bin\Debug\Renci.SshNet.xml - true - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE;FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - prompt - 4 - bin\Release\Renci.SshNet.xml - true - - - x86 - true - bin\x86\Debug\ - TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - ;2008 - full - x86 - false - prompt - - - x86 - bin\x86\Release\ - TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - true - ;2008 - pdbonly - x86 - false - prompt - - - ARM - true - bin\ARM\Debug\ - TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - ;2008 - full - ARM - false - prompt - - - ARM - bin\ARM\Release\ - TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - true - ;2008 - pdbonly - ARM - false - prompt - - - x64 - true - bin\x64\Debug\ - TRACE;DEBUG;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - ;2008 - full - x64 - false - prompt - - - x64 - bin\x64\Release\ - TRACE;FEATURE_DATAGRAMSOCKET;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_ENCODING_ASCII - true - ;2008 - pdbonly - x64 - false - prompt - - - - - - - - Abstractions\CryptoAbstraction.cs - - - Abstractions\DiagnosticAbstraction.cs - - - Abstractions\DnsAbstraction.cs - - - Abstractions\FileSystemAbstraction.cs - - - Abstractions\ReflectionAbstraction.cs - - - Abstractions\SocketAbstraction.cs - - - Abstractions\ThreadAbstraction.cs - - - AuthenticationMethod.cs - - - AuthenticationResult.cs - - - BaseClient.cs - - - Channels\Channel.cs - - - Channels\ChannelDirectTcpip.cs - - - Channels\ChannelForwardedTcpip.cs - - - Channels\ChannelSession.cs - - - Channels\ChannelTypes.cs - - - Channels\ClientChannel.cs - - - Channels\IChannel.cs - - - Channels\IChannelDirectTcpip.cs - - - Channels\IChannelForwardedTcpip.cs - - - Channels\IChannelSession.cs - - - Channels\ServerChannel.cs - - - CipherInfo.cs - - - ClientAuthentication.cs - - - CommandAsyncResult.cs - - - Common\Array.cs - - - Common\ASCIIEncoding.cs - - - Common\AsyncResult.cs - - - Common\AuthenticationBannerEventArgs.cs - - - Common\AuthenticationEventArgs.cs - - - Common\AuthenticationPasswordChangeEventArgs.cs - - - Common\AuthenticationPrompt.cs - - - Common\AuthenticationPromptEventArgs.cs - - - Common\BigInteger.cs - - - Common\ChannelDataEventArgs.cs - - - Common\ChannelEventArgs.cs - - - Common\ChannelExtendedDataEventArgs.cs - - - Common\ChannelOpenConfirmedEventArgs.cs - - - Common\ChannelOpenFailedEventArgs.cs - - - Common\ChannelRequestEventArgs.cs - - - Common\CountdownEvent.cs - - - Common\DerData.cs - - - Common\ExceptionEventArgs.cs - - - Common\Extensions.cs - - - Common\HostKeyEventArgs.cs - - - Common\NetConfServerException.cs - - - Common\ObjectIdentifier.cs - - - Common\Pack.cs - - - Common\PacketDump.cs - - - Common\PipeStream.cs - - - Common\PortForwardEventArgs.cs - - - Common\PosixPath.cs - - - Common\ProxyException.cs - - - Common\ScpDownloadEventArgs.cs - - - Common\ScpException.cs - - - Common\ScpUploadEventArgs.cs - - - Common\SemaphoreLight.cs - - - Common\SftpPathNotFoundException.cs - - - Common\SftpPermissionDeniedException.cs - - - Common\ShellDataEventArgs.cs - - - Common\SshAuthenticationException.cs - - - Common\SshConnectionException.cs - - - Common\SshData.cs - - - Common\SshDataStream.cs - - - Common\SshException.cs - - - Common\SshOperationTimeoutException.cs - - - Common\SshPassPhraseNullOrEmptyException.cs - - - Common\TerminalModes.cs - - - Compression\CompressionMode.cs - - - Compression\Compressor.cs - - - Compression\Zlib.cs - - - Compression\ZlibOpenSsh.cs - - - Compression\ZlibStream.cs - - - ConnectionInfo.cs - - - Connection\ConnectorBase.cs - - - Connection\DirectConnector.cs - - - Connection\HttpConnector.cs - - - Connection\IConnector.cs - - - Connection\IProtocolVersionExchange.cs - - - Connection\ISocketFactory.cs - - - Connection\ProtocolVersionExchange.cs - - - Connection\SocketFactory.cs - - - Connection\Socks4Connector.cs - - - Connection\Socks5Connector.cs - - - Connection\SshIdentification.cs - - - ExpectAction.cs - - - ExpectAsyncResult.cs - - - ForwardedPort.cs - - - ForwardedPortDynamic.cs - - - ForwardedPortDynamic.NET.cs - - - ForwardedPortLocal.cs - - - ForwardedPortLocal.NET.cs - - - ForwardedPortRemote.cs - - - ForwardedPortStatus.cs - - - HashInfo.cs - - - IAuthenticationMethod.cs - - - IClientAuthentication.cs - - - IConnectionInfo.cs - - - IForwardedPort.cs - - - IRemotePathTransformation.cs - - - IServiceFactory.cs - - - IServiceFactory.NET.cs - - - ISession.cs - - - ISftpClient.cs - - - ISubsystemSession.cs - - - KeyboardInteractiveAuthenticationMethod.cs - - - KeyboardInteractiveConnectionInfo.cs - - - MessageEventArgs.cs - - - Messages\Authentication\BannerMessage.cs - - - Messages\Authentication\FailureMessage.cs - - - Messages\Authentication\InformationRequestMessage.cs - - - Messages\Authentication\InformationResponseMessage.cs - - - Messages\Authentication\PasswordChangeRequiredMessage.cs - - - Messages\Authentication\PublicKeyMessage.cs - - - Messages\Authentication\RequestMessage.cs - - - Messages\Authentication\RequestMessageHost.cs - - - Messages\Authentication\RequestMessageKeyboardInteractive.cs - - - Messages\Authentication\RequestMessageNone.cs - - - Messages\Authentication\RequestMessagePassword.cs - - - Messages\Authentication\RequestMessagePublicKey.cs - - - Messages\Authentication\SuccessMessage.cs - - - Messages\Connection\CancelTcpIpForwardGlobalRequestMessage.cs - - - Messages\Connection\ChannelCloseMessage.cs - - - Messages\Connection\ChannelDataMessage.cs - - - Messages\Connection\ChannelEofMessage.cs - - - Messages\Connection\ChannelExtendedDataMessage.cs - - - Messages\Connection\ChannelFailureMessage.cs - - - Messages\Connection\ChannelMessage.cs - - - Messages\Connection\ChannelOpenConfirmationMessage.cs - - - Messages\Connection\ChannelOpenFailureMessage.cs - - - Messages\Connection\ChannelOpenFailureReasons.cs - - - Messages\Connection\ChannelOpen\ChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\ChannelOpenMessage.cs - - - Messages\Connection\ChannelOpen\DirectTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\ForwardedTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\SessionChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\X11ChannelOpenInfo.cs - - - Messages\Connection\ChannelRequest\BreakRequestInfo.cs - - - Messages\Connection\ChannelRequest\ChannelRequestMessage.cs - - - Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs - - - Messages\Connection\ChannelRequest\EnvironmentVariableRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExecRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitSignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitStatusRequestInfo.cs - - - Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs - - - Messages\Connection\ChannelRequest\PseudoTerminalInfo.cs - - - Messages\Connection\ChannelRequest\RequestInfo.cs - - - Messages\Connection\ChannelRequest\ShellRequestInfo.cs - - - Messages\Connection\ChannelRequest\SignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\SubsystemRequestInfo.cs - - - Messages\Connection\ChannelRequest\WindowChangeRequestInfo.cs - - - Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs - - - Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs - - - Messages\Connection\ChannelSuccessMessage.cs - - - Messages\Connection\ChannelWindowAdjustMessage.cs - - - Messages\Connection\GlobalRequestMessage.cs - - - Messages\Connection\GlobalRequestName.cs - - - Messages\Connection\RequestFailureMessage.cs - - - Messages\Connection\RequestSuccessMessage.cs - - - Messages\Connection\TcpIpForwardGlobalRequestMessage.cs - - - Messages\Message.cs - - - Messages\MessageAttribute.cs - - - Messages\ServiceName.cs - - - Messages\Transport\DebugMessage.cs - - - Messages\Transport\DisconnectMessage.cs - - - Messages\Transport\DisconnectReason.cs - - - Messages\Transport\IgnoreMessage.cs - - - Messages\Transport\IKeyExchangedAllowed.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeGroup.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeInit.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeReply.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs - - - Messages\Transport\KeyExchangeDhInitMessage.cs - - - Messages\Transport\KeyExchangeDhReplyMessage.cs - - - Messages\Transport\KeyExchangeEcdhInitMessage.cs - - - Messages\Transport\KeyExchangeEcdhReplyMessage.cs - - - Messages\Transport\KeyExchangeInitMessage.cs - - - Messages\Transport\NewKeysMessage.cs - - - Messages\Transport\ServiceAcceptMessage.cs - - - Messages\Transport\ServiceRequestMessage.cs - - - Messages\Transport\UnimplementedMessage.cs - - - NetConfClient.cs - - - Netconf\INetConfSession.cs - - - Netconf\NetConfSession.cs - - - NoneAuthenticationMethod.cs - - - PasswordAuthenticationMethod.cs - - - PasswordConnectionInfo.cs - - - PrivateKeyAuthenticationMethod.cs - - - PrivateKeyConnectionInfo.cs - - - PrivateKeyFile.cs - - - Properties\CommonAssemblyInfo.cs - - - ProxyTypes.cs - - - RemotePathDoubleQuoteTransformation.cs - - - RemotePathNoneTransformation.cs - - - RemotePathShellQuoteTransformation.cs - - - RemotePathTransformation.cs - - - ScpClient.cs - - - ScpClient.NET.cs - - - Security\Algorithm.cs - - - Security\Cryptography\BouncyCastle\asn1\sec\SECNamedCurves.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9Curve.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParameters.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParametersHolder.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECPoint.cs - - - Security\Cryptography\BouncyCastle\crypto\agreement\ECDHCBasicAgreement.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricCipherKeyPair.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricKeyParameter.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\GeneralDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\Sha256Digest.cs - - - Security\Cryptography\BouncyCastle\crypto\generators\ECKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IAsymmetricCipherKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\KeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECDomainParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPrivateKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPublicKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\CryptoApiRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\DigestRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\IRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\util\Pack.cs - - - Security\Cryptography\BouncyCastle\math\BigInteger.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\SimpleBigDecimal.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\Tnaf.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\ZTauElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECAlgorithms.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECCurve.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECFieldElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECLookupTable.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPoint.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPointMap.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\ECEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\GlvEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\LongArray.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\AbstractECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointCombMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\GlvMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\IPreCompCallback.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\PreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ValidityPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafL2RMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\field\FiniteFields.cs - - - Security\Cryptography\BouncyCastle\math\field\GenericPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\GF2Polynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\IFiniteField.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\PrimeField.cs - - - Security\Cryptography\BouncyCastle\math\raw\Mod.cs - - - Security\Cryptography\BouncyCastle\math\raw\Nat.cs - - - Security\Cryptography\BouncyCastle\security\DigestUtilities.cs - - - Security\Cryptography\BouncyCastle\security\SecureRandom.cs - - - Security\Cryptography\BouncyCastle\security\SecurityUtilityException.cs - - - Security\Cryptography\BouncyCastle\util\Arrays.cs - - - Security\Cryptography\BouncyCastle\util\BigIntegers.cs - - - Security\Cryptography\BouncyCastle\util\encoders\Hex.cs - - - Security\Cryptography\BouncyCastle\util\encoders\HexEncoder.cs - - - Security\Cryptography\BouncyCastle\util\IMemoable.cs - - - Security\Cryptography\BouncyCastle\util\Integers.cs - - - Security\Cryptography\BouncyCastle\util\MemoableResetException.cs - - - Security\Cryptography\BouncyCastle\util\Times.cs - - - Security\CertificateHostAlgorithm.cs - - - Security\Cryptography\Chaos.NaCl\CryptoBytes.cs - - - Security\Cryptography\Chaos.NaCl\Ed25519.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array16.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array8.cs - - - Security\Cryptography\Chaos.NaCl\Internal\ByteIntegerConverter.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cmov.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cswap.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_invert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnegative.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnonzero.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul121666.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_neg.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_pow22523.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\FieldElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_double_scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_madd.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_msub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p3.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_cached.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_precomp_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_scalarmult_base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\GroupElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\keypair.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\open.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_clamp.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_mul_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_reduce.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sign.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sqrtm1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\InternalAssert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Poly1305Donna.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\Salsa20.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\SalsaCore.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Sha512Internal.cs - - - Security\Cryptography\Chaos.NaCl\MontgomeryCurve25519.cs - - - Security\Cryptography\Chaos.NaCl\Sha512.cs - - - Security\Cryptography\AsymmetricCipher.cs - - - Security\Cryptography\Bcrypt.cs - - - Security\Cryptography\BlockCipher.cs - - - Security\Cryptography\Cipher.cs - - - Security\Cryptography\CipherDigitalSignature.cs - - - Security\Cryptography\Ciphers\AesCipher.cs - - - Security\Cryptography\Ciphers\Arc4Cipher.cs - - - Security\Cryptography\Ciphers\BlowfishCipher.cs - - - Security\Cryptography\Ciphers\CastCipher.cs - - - Security\Cryptography\Ciphers\CipherMode.cs - - - Security\Cryptography\Ciphers\CipherPadding.cs - - - Security\Cryptography\Ciphers\DesCipher.cs - - - Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS5Padding.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs - - - Security\Cryptography\Ciphers\RsaCipher.cs - - - Security\Cryptography\Ciphers\SerpentCipher.cs - - - Security\Cryptography\Ciphers\TripleDesCipher.cs - - - Security\Cryptography\Ciphers\TwofishCipher.cs - - - Security\Cryptography\DigitalSignature.cs - - - Security\Cryptography\DsaDigitalSignature.cs - - - Security\Cryptography\DsaKey.cs - - - Security\Cryptography\ED25519DigitalSignature.cs - - - Security\Cryptography\ED25519Key.cs - - - Security\Cryptography\HMACMD5.cs - - - Security\Cryptography\HMACSHA1.cs - - - Security\Cryptography\HMACSHA256.cs - - - Security\Cryptography\HMACSHA384.cs - - - Security\Cryptography\HMACSHA512.cs - - - Security\Cryptography\Key.cs - - - Security\Cryptography\EcdsaDigitalSignature.cs - - - Security\Cryptography\EcdsaKey.cs - - - Security\Cryptography\RsaDigitalSignature.cs - - - Security\Cryptography\RsaKey.cs - - - Security\Cryptography\StreamCipher.cs - - - Security\Cryptography\SymmetricCipher.cs - - - Security\GroupExchangeHashData.cs - - - Security\HostAlgorithm.cs - - - Security\IKeyExchange.cs - - - Security\KeyExchange.cs - - - Security\KeyExchangeDiffieHellman.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha256.cs - - - Security\KeyExchangeDiffieHellmanGroup16Sha512.cs - - - Security\KeyExchangeDiffieHellmanGroup1Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs - - - Security\KeyExchangeDiffieHellmanGroupSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupSha512.cs - - - Security\KeyExchangeDiffieHellmanGroupShaBase.cs - - - Security\KeyExchangeEC.cs - - - Security\KeyExchangeECCurve25519.cs - - - Security\KeyExchangeECDH.cs - - - Security\KeyExchangeECDH256.cs - - - Security\KeyExchangeECDH384.cs - - - Security\KeyExchangeECDH521.cs - - - Security\KeyExchangeHash.cs - - - Security\KeyHostAlgorithm.cs - - - ServiceFactory.cs - - - ServiceFactory.NET.cs - - - Session.cs - - - SftpClient.cs - - - Sftp\Flags.cs - - - Sftp\ISftpFileReader.cs - - - Sftp\ISftpResponseFactory.cs - - - Sftp\ISftpSession.cs - - - Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs - - - Sftp\Requests\ExtendedRequests\HardLinkRequest.cs - - - Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs - - - Sftp\Requests\ExtendedRequests\StatVfsRequest.cs - - - Sftp\Requests\SftpBlockRequest.cs - - - Sftp\Requests\SftpCloseRequest.cs - - - Sftp\Requests\SftpExtendedRequest.cs - - - Sftp\Requests\SftpFSetStatRequest.cs - - - Sftp\Requests\SftpFStatRequest.cs - - - Sftp\Requests\SftpInitRequest.cs - - - Sftp\Requests\SftpLinkRequest.cs - - - Sftp\Requests\SftpLStatRequest.cs - - - Sftp\Requests\SftpMkDirRequest.cs - - - Sftp\Requests\SftpOpenDirRequest.cs - - - Sftp\Requests\SftpOpenRequest.cs - - - Sftp\Requests\SftpReadDirRequest.cs - - - Sftp\Requests\SftpReadLinkRequest.cs - - - Sftp\Requests\SftpReadRequest.cs - - - Sftp\Requests\SftpRealPathRequest.cs - - - Sftp\Requests\SftpRemoveRequest.cs - - - Sftp\Requests\SftpRenameRequest.cs - - - Sftp\Requests\SftpRequest.cs - - - Sftp\Requests\SftpRmDirRequest.cs - - - Sftp\Requests\SftpSetStatRequest.cs - - - Sftp\Requests\SftpStatRequest.cs - - - Sftp\Requests\SftpSymLinkRequest.cs - - - Sftp\Requests\SftpUnblockRequest.cs - - - Sftp\Requests\SftpWriteRequest.cs - - - Sftp\Responses\ExtendedReplies\ExtendedReplyInfo.cs - - - Sftp\Responses\ExtendedReplies\StatVfsReplyInfo.cs - - - Sftp\Responses\SftpAttrsResponse.cs - - - Sftp\Responses\SftpDataResponse.cs - - - Sftp\Responses\SftpExtendedReplyResponse.cs - - - Sftp\Responses\SftpHandleResponse.cs - - - Sftp\Responses\SftpNameResponse.cs - - - Sftp\Responses\SftpResponse.cs - - - Sftp\Responses\SftpStatusResponse.cs - - - Sftp\Responses\SftpVersionResponse.cs - - - Sftp\SftpCloseAsyncResult.cs - - - Sftp\SftpDownloadAsyncResult.cs - - - Sftp\SftpFile.cs - - - Sftp\ISftpFile.cs - - - Sftp\SftpFileAttributes.cs - - - Sftp\SftpFileReader.cs - - - Sftp\SftpFileStream.cs - - - Sftp\SftpFileSystemInformation.cs - - - Sftp\SftpListDirectoryAsyncResult.cs - - - Sftp\SftpMessage.cs - - - Sftp\SftpMessageTypes.cs - - - Sftp\SftpOpenAsyncResult.cs - - - Sftp\SftpReadAsyncResult.cs - - - Sftp\SftpRealPathAsyncResult.cs - - - Sftp\SftpResponseFactory.cs - - - Sftp\SftpSession.cs - - - Sftp\SFtpStatAsyncResult.cs - - - Sftp\SftpSynchronizeDirectoriesAsyncResult.cs - - - Sftp\SftpUploadAsyncResult.cs - - - Sftp\StatusCodes.cs - - - Shell.cs - - - ShellStream.cs - - - SshClient.cs - - - SshCommand.cs - - - SshMessageFactory.cs - - - SubsystemSession.cs - - - - - - 14.0 - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.UAP10/project.json b/src/Renci.SshNet.UAP10/project.json deleted file mode 100644 index 6916d5e63..000000000 --- a/src/Renci.SshNet.UAP10/project.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "dependencies": { - "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.0", - "SshNet.Security.Cryptography": "1.2.0", - "System.Xml.XPath.XmlDocument": "4.0.1" - }, - "frameworks": { - "uap10.0": {} - }, - "runtimes": { - "win10-arm": {}, - "win10-arm-aot": {}, - "win10-x86": {}, - "win10-x86-aot": {}, - "win10-x64": {}, - "win10-x64-aot": {} - } -} \ No newline at end of file diff --git a/src/Renci.SshNet.VS2012.sln b/src/Renci.SshNet.VS2012.sln deleted file mode 100644 index a80b19085..000000000 --- a/src/Renci.SshNet.VS2012.sln +++ /dev/null @@ -1,108 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.Silverlight", "Renci.SshNet.Silverlight\Renci.SshNet.Silverlight.csproj", "{77C294BB-1DC2-49DC-BE16-963F8F22794D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.WindowsPhone", "Renci.SshNet.WindowsPhone\Renci.SshNet.WindowsPhone.csproj", "{3AD3EDF0-702E-4A91-8735-DCE4659AA54C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.Silverlight5", "Renci.SshNet.Silverlight5\Renci.SshNet.Silverlight5.csproj", "{E367F791-C1EC-4181-912A-2943CAC6B3BC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.WindowsPhone8", "Renci.SshNet.WindowsPhone8\Renci.SshNet.WindowsPhone8.csproj", "{4A6CA785-1C8A-47FE-98C0-30C675A9328B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D}" - ProjectSection(SolutionItems) = preProject - ..\build\build.proj = ..\build\build.proj - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{94EE3919-19FA-4D9B-8DA9-249050B15232}" - ProjectSection(SolutionItems) = preProject - ..\build\nuget\SSH.NET.nuspec = ..\build\nuget\SSH.NET.nuspec - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandcastle", "sandcastle", "{A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1}" - ProjectSection(SolutionItems) = preProject - ..\build\sandcastle\SSH.NET.shfbproj = ..\build\sandcastle\SSH.NET.shfbproj - EndProjectSection -EndProject -Global - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Renci.SshNet1.vsmdi - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|Mixed Platforms = Release|Mixed Platforms - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|ARM.ActiveCfg = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|x64.ActiveCfg = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Debug|x86.ActiveCfg = Debug|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Any CPU.Build.0 = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|ARM.ActiveCfg = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|x64.ActiveCfg = Release|Any CPU - {77C294BB-1DC2-49DC-BE16-963F8F22794D}.Release|x86.ActiveCfg = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|ARM.ActiveCfg = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|x64.ActiveCfg = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Debug|x86.ActiveCfg = Debug|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|Any CPU.Build.0 = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|ARM.ActiveCfg = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|x64.ActiveCfg = Release|Any CPU - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C}.Release|x86.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|ARM.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|x64.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|x86.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Any CPU.Build.0 = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|ARM.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|x64.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|x86.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|ARM.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|x64.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|x86.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Any CPU.Build.0 = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|ARM.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|x64.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|x86.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {94EE3919-19FA-4D9B-8DA9-249050B15232} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - {A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - EndGlobalSection -EndGlobal diff --git a/src/Renci.SshNet.VS2015.sln b/src/Renci.SshNet.VS2015.sln deleted file mode 100644 index 81fa71554..000000000 --- a/src/Renci.SshNet.VS2015.sln +++ /dev/null @@ -1,130 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D}" - ProjectSection(SolutionItems) = preProject - ..\build\build.proj = ..\build\build.proj - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{94EE3919-19FA-4D9B-8DA9-249050B15232}" - ProjectSection(SolutionItems) = preProject - ..\build\nuget\SSH.NET.nuspec = ..\build\nuget\SSH.NET.nuspec - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandcastle", "sandcastle", "{A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1}" - ProjectSection(SolutionItems) = preProject - ..\build\sandcastle\SSH.NET.shfbproj = ..\build\sandcastle\SSH.NET.shfbproj - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.Silverlight5", "Renci.SshNet.Silverlight5\Renci.SshNet.Silverlight5.csproj", "{E367F791-C1EC-4181-912A-2943CAC6B3BC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.WindowsPhone8", "Renci.SshNet.WindowsPhone8\Renci.SshNet.WindowsPhone8.csproj", "{4A6CA785-1C8A-47FE-98C0-30C675A9328B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.UAP10", "Renci.SshNet.UAP10\Renci.SshNet.UAP10.csproj", "{EC212E04-A372-4B95-B45B-C0D4A739EF80}" -EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Renci.SshNet.Shared.Tests", "..\test\Renci.SshNet.Shared.Tests\Renci.SshNet.Shared.Tests.shproj", "{FAE3948F-A438-458E-8E0E-7F6E39A5DD8A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Renci.SshNet.WindowsPhone8.Tests", "..\test\Renci.SshNet.WindowsPhone8.Tests\Renci.SshNet.WindowsPhone8.Tests.csproj", "{26F0D644-B3EF-47DF-8040-E9E4B2E63884}" -EndProject -Global - GlobalSection(SharedMSBuildProjectFiles) = preSolution - ..\test\Renci.SshNet.Shared.Tests\Renci.SshNet.Shared.Tests.projitems*{26f0d644-b3ef-47df-8040-e9e4b2e63884}*SharedItemsImports = 4 - ..\test\Renci.SshNet.Shared.Tests\Renci.SshNet.Shared.Tests.projitems*{fae3948f-a438-458e-8e0e-7f6e39a5dd8a}*SharedItemsImports = 13 - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|Mixed Platforms = Release|Mixed Platforms - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|ARM.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|x64.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Debug|x86.ActiveCfg = Debug|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Any CPU.Build.0 = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|ARM.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|x64.ActiveCfg = Release|Any CPU - {E367F791-C1EC-4181-912A-2943CAC6B3BC}.Release|x86.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|ARM.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|x64.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Debug|x86.ActiveCfg = Debug|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Any CPU.Build.0 = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|ARM.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|x64.ActiveCfg = Release|Any CPU - {4A6CA785-1C8A-47FE-98C0-30C675A9328B}.Release|x86.ActiveCfg = Release|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|ARM.ActiveCfg = Debug|ARM - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|ARM.Build.0 = Debug|ARM - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|x64.ActiveCfg = Debug|x64 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|x64.Build.0 = Debug|x64 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|x86.ActiveCfg = Debug|x86 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Debug|x86.Build.0 = Debug|x86 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|Any CPU.Build.0 = Release|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|ARM.ActiveCfg = Release|ARM - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|ARM.Build.0 = Release|ARM - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|x64.ActiveCfg = Release|x64 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|x64.Build.0 = Release|x64 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|x86.ActiveCfg = Release|x86 - {EC212E04-A372-4B95-B45B-C0D4A739EF80}.Release|x86.Build.0 = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|Any CPU.ActiveCfg = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|ARM.ActiveCfg = Debug|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|ARM.Build.0 = Debug|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|ARM.Deploy.0 = Debug|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|Mixed Platforms.Deploy.0 = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|x64.ActiveCfg = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|x86.ActiveCfg = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|x86.Build.0 = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Debug|x86.Deploy.0 = Debug|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|Any CPU.ActiveCfg = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|ARM.ActiveCfg = Release|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|ARM.Build.0 = Release|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|ARM.Deploy.0 = Release|ARM - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|Mixed Platforms.ActiveCfg = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|Mixed Platforms.Build.0 = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|Mixed Platforms.Deploy.0 = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|x64.ActiveCfg = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|x86.ActiveCfg = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|x86.Build.0 = Release|x86 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884}.Release|x86.Deploy.0 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {94EE3919-19FA-4D9B-8DA9-249050B15232} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - {A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - EndGlobalSection - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Renci.SshNet1.vsmdi - EndGlobalSection -EndGlobal diff --git a/src/Renci.SshNet.VS2015.sln.DotSettings b/src/Renci.SshNet.VS2015.sln.DotSettings deleted file mode 100644 index 15b1b217e..000000000 --- a/src/Renci.SshNet.VS2015.sln.DotSettings +++ /dev/null @@ -1,22 +0,0 @@ - - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - SUGGESTION - WARNING - DO_NOT_SHOW - DO_NOT_SHOW - DO_NOT_SHOW - True - True - True - NEXT_LINE_SHIFTED_2 - CHOP_IF_LONG - HMACMD - HMACSHA - True - True - True - integration,LongRunning \ No newline at end of file diff --git a/src/Renci.SshNet.VS2017.sln b/src/Renci.SshNet.VS2017.sln deleted file mode 100644 index 9f1ce5e37..000000000 --- a/src/Renci.SshNet.VS2017.sln +++ /dev/null @@ -1,82 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26014.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D}" - ProjectSection(SolutionItems) = preProject - ..\build\build.cmd = ..\build\build.cmd - ..\build\build.proj = ..\build\build.proj - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{94EE3919-19FA-4D9B-8DA9-249050B15232}" - ProjectSection(SolutionItems) = preProject - ..\build\nuget\SSH.NET.nuspec = ..\build\nuget\SSH.NET.nuspec - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sandcastle", "sandcastle", "{A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1}" - ProjectSection(SolutionItems) = preProject - ..\build\sandcastle\SSH.NET.shfbproj = ..\build\sandcastle\SSH.NET.shfbproj - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet", "Renci.SshNet\Renci.SshNet.csproj", "{2F5F8C90-0BD1-424F-997C-7BC6280919D1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet.Tests", "Renci.SshNet.Tests\Renci.SshNet.Tests.csproj", "{C45379B9-17B1-4E89-BC2E-6D41726413E8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM - Release|Mixed Platforms = Release|Mixed Platforms - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|ARM.ActiveCfg = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|x64.ActiveCfg = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Debug|x86.ActiveCfg = Debug|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Any CPU.Build.0 = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|ARM.ActiveCfg = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|x64.ActiveCfg = Release|Any CPU - {2F5F8C90-0BD1-424F-997C-7BC6280919D1}.Release|x86.ActiveCfg = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|ARM.ActiveCfg = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|x64.ActiveCfg = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Debug|x86.ActiveCfg = Debug|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Any CPU.Build.0 = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|ARM.ActiveCfg = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|x64.ActiveCfg = Release|Any CPU - {C45379B9-17B1-4E89-BC2E-6D41726413E8}.Release|x86.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {94EE3919-19FA-4D9B-8DA9-249050B15232} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - {A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {C3D130B3-A070-4B12-A10F-E3E44D6ACEE2} - EndGlobalSection - GlobalSection(TestCaseManagementSettings) = postSolution - CategoryFile = Renci.SshNet1.vsmdi - EndGlobalSection -EndGlobal diff --git a/src/Renci.SshNet.WindowsPhone/Properties/AssemblyInfo.cs b/src/Renci.SshNet.WindowsPhone/Properties/AssemblyInfo.cs deleted file mode 100644 index f61fb1340..000000000 --- a/src/Renci.SshNet.WindowsPhone/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,5 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SSH.NET Windows Phone 7.1")] -[assembly: Guid("b044a9d9-fe40-4d7e-b198-c142ab9721f0")] diff --git a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj b/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj deleted file mode 100644 index f8342e11b..000000000 --- a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj +++ /dev/null @@ -1,1435 +0,0 @@ - - - - Debug - AnyCPU - 10.0.20506 - 2.0 - {3AD3EDF0-702E-4A91-8735-DCE4659AA54C} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Renci.SshNet - Renci.SshNet - v4.0 - $(TargetFrameworkVersion) - WindowsPhone71 - Silverlight - false - true - true - - - true - full - false - Bin\Debug - TRACE;DEBUG;FEATURE_DEVICEINFORMATION_APM;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_SHA1;FEATURE_HASH_SHA256;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - Bin\Debug\Renci.SshNet.xml - - - none - true - Bin\Release - TRACE;FEATURE_DEVICEINFORMATION_APM;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_SHA1;FEATURE_HASH_SHA256;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - Bin\Release\Renci.SshNet.xml - 1591 - - - - - False - ..\..\packages\SshNet.Security.Cryptography.1.2.0\lib\wp71\SshNet.Security.Cryptography.dll - - - - - - - Abstractions\CryptoAbstraction.cs - - - Abstractions\DiagnosticAbstraction.cs - - - Abstractions\DnsAbstraction.cs - - - Abstractions\FileSystemAbstraction.cs - - - Abstractions\ReflectionAbstraction.cs - - - Abstractions\SocketAbstraction.cs - - - Abstractions\ThreadAbstraction.cs - - - AuthenticationMethod.cs - - - AuthenticationResult.cs - - - BaseClient.cs - - - Channels\Channel.cs - - - Channels\ChannelDirectTcpip.cs - - - Channels\ChannelForwardedTcpip.cs - - - Channels\ChannelSession.cs - - - Channels\ChannelTypes.cs - - - Channels\ClientChannel.cs - - - Channels\IChannel.cs - - - Channels\IChannelDirectTcpip.cs - - - Channels\IChannelForwardedTcpip.cs - - - Channels\IChannelSession.cs - - - Channels\ServerChannel.cs - - - CipherInfo.cs - - - ClientAuthentication.cs - - - CommandAsyncResult.cs - - - Common\Array.cs - - - Common\ASCIIEncoding.cs - - - Common\AsyncResult.cs - - - Common\AuthenticationBannerEventArgs.cs - - - Common\AuthenticationEventArgs.cs - - - Common\AuthenticationPasswordChangeEventArgs.cs - - - Common\AuthenticationPrompt.cs - - - Common\AuthenticationPromptEventArgs.cs - - - Common\BigInteger.cs - - - Common\ChannelDataEventArgs.cs - - - Common\ChannelEventArgs.cs - - - Common\ChannelExtendedDataEventArgs.cs - - - Common\ChannelOpenConfirmedEventArgs.cs - - - Common\ChannelOpenFailedEventArgs.cs - - - Common\ChannelRequestEventArgs.cs - - - Common\CountdownEvent.cs - - - Common\DerData.cs - - - Common\ExceptionEventArgs.cs - - - Common\Extensions.cs - - - Common\HostKeyEventArgs.cs - - - Common\ObjectIdentifier.cs - - - Common\Pack.cs - - - Common\PacketDump.cs - - - Common\PipeStream.cs - - - Common\PortForwardEventArgs.cs - - - Common\PosixPath.cs - - - Common\ProxyException.cs - - - Common\ScpDownloadEventArgs.cs - - - Common\ScpException.cs - - - Common\ScpUploadEventArgs.cs - - - Common\SemaphoreLight.cs - - - Common\SftpPathNotFoundException.cs - - - Common\SftpPermissionDeniedException.cs - - - Common\ShellDataEventArgs.cs - - - Common\SshAuthenticationException.cs - - - Common\SshConnectionException.cs - - - Common\SshData.cs - - - Common\SshDataStream.cs - - - Common\SshException.cs - - - Common\SshOperationTimeoutException.cs - - - Common\SshPassPhraseNullOrEmptyException.cs - - - Common\TerminalModes.cs - - - Compression\CompressionMode.cs - - - Compression\Compressor.cs - - - Compression\Zlib.cs - - - Compression\ZlibOpenSsh.cs - - - Compression\ZlibStream.cs - - - ConnectionInfo.cs - - - Connection\ConnectorBase.cs - - - Connection\DirectConnector.cs - - - Connection\HttpConnector.cs - - - Connection\IConnector.cs - - - Connection\IProtocolVersionExchange.cs - - - Connection\ISocketFactory.cs - - - Connection\ProtocolVersionExchange.cs - - - Connection\SocketFactory.cs - - - Connection\Socks4Connector.cs - - - Connection\Socks5Connector.cs - - - Connection\SshIdentification.cs - - - ExpectAction.cs - - - ExpectAsyncResult.cs - - - ForwardedPort.cs - - - ForwardedPortDynamic.cs - - - ForwardedPortLocal.cs - - - ForwardedPortRemote.cs - - - ForwardedPortStatus.cs - - - HashInfo.cs - - - IAuthenticationMethod.cs - - - IClientAuthentication.cs - - - IConnectionInfo.cs - - - IForwardedPort.cs - - - IRemotePathTransformation.cs - - - IServiceFactory.cs - - - ISession.cs - - - ISubsystemSession.cs - - - KeyboardInteractiveAuthenticationMethod.cs - - - KeyboardInteractiveConnectionInfo.cs - - - MessageEventArgs.cs - - - Messages\Authentication\BannerMessage.cs - - - Messages\Authentication\FailureMessage.cs - - - Messages\Authentication\InformationRequestMessage.cs - - - Messages\Authentication\InformationResponseMessage.cs - - - Messages\Authentication\PasswordChangeRequiredMessage.cs - - - Messages\Authentication\PublicKeyMessage.cs - - - Messages\Authentication\RequestMessage.cs - - - Messages\Authentication\RequestMessageHost.cs - - - Messages\Authentication\RequestMessageKeyboardInteractive.cs - - - Messages\Authentication\RequestMessageNone.cs - - - Messages\Authentication\RequestMessagePassword.cs - - - Messages\Authentication\RequestMessagePublicKey.cs - - - Messages\Authentication\SuccessMessage.cs - - - Messages\Connection\CancelTcpIpForwardGlobalRequestMessage.cs - - - Messages\Connection\ChannelCloseMessage.cs - - - Messages\Connection\ChannelDataMessage.cs - - - Messages\Connection\ChannelEofMessage.cs - - - Messages\Connection\ChannelExtendedDataMessage.cs - - - Messages\Connection\ChannelFailureMessage.cs - - - Messages\Connection\ChannelMessage.cs - - - Messages\Connection\ChannelOpenConfirmationMessage.cs - - - Messages\Connection\ChannelOpenFailureMessage.cs - - - Messages\Connection\ChannelOpenFailureReasons.cs - - - Messages\Connection\ChannelOpen\ChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\ChannelOpenMessage.cs - - - Messages\Connection\ChannelOpen\DirectTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\ForwardedTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\SessionChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\X11ChannelOpenInfo.cs - - - Messages\Connection\ChannelRequest\BreakRequestInfo.cs - - - Messages\Connection\ChannelRequest\ChannelRequestMessage.cs - - - Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs - - - Messages\Connection\ChannelRequest\EnvironmentVariableRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExecRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitSignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitStatusRequestInfo.cs - - - Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs - - - Messages\Connection\ChannelRequest\PseudoTerminalInfo.cs - - - Messages\Connection\ChannelRequest\RequestInfo.cs - - - Messages\Connection\ChannelRequest\ShellRequestInfo.cs - - - Messages\Connection\ChannelRequest\SignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\SubsystemRequestInfo.cs - - - Messages\Connection\ChannelRequest\WindowChangeRequestInfo.cs - - - Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs - - - Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs - - - Messages\Connection\ChannelSuccessMessage.cs - - - Messages\Connection\ChannelWindowAdjustMessage.cs - - - Messages\Connection\GlobalRequestMessage.cs - - - Messages\Connection\GlobalRequestName.cs - - - Messages\Connection\RequestFailureMessage.cs - - - Messages\Connection\RequestSuccessMessage.cs - - - Messages\Connection\TcpIpForwardGlobalRequestMessage.cs - - - Messages\Message.cs - - - Messages\MessageAttribute.cs - - - Messages\ServiceName.cs - - - Messages\Transport\DebugMessage.cs - - - Messages\Transport\DisconnectMessage.cs - - - Messages\Transport\DisconnectReason.cs - - - Messages\Transport\IgnoreMessage.cs - - - Messages\Transport\IKeyExchangedAllowed.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeGroup.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeInit.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeReply.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs - - - Messages\Transport\KeyExchangeDhInitMessage.cs - - - Messages\Transport\KeyExchangeDhReplyMessage.cs - - - Messages\Transport\KeyExchangeEcdhInitMessage.cs - - - Messages\Transport\KeyExchangeEcdhReplyMessage.cs - - - Messages\Transport\KeyExchangeInitMessage.cs - - - Messages\Transport\NewKeysMessage.cs - - - Messages\Transport\ServiceAcceptMessage.cs - - - Messages\Transport\ServiceRequestMessage.cs - - - Messages\Transport\UnimplementedMessage.cs - - - NoneAuthenticationMethod.cs - - - PasswordAuthenticationMethod.cs - - - PasswordConnectionInfo.cs - - - PrivateKeyAuthenticationMethod.cs - - - PrivateKeyConnectionInfo.cs - - - PrivateKeyFile.cs - - - ProxyTypes.cs - - - RemotePathDoubleQuoteTransformation.cs - - - RemotePathNoneTransformation.cs - - - RemotePathShellQuoteTransformation.cs - - - RemotePathTransformation.cs - - - ScpClient.cs - - - Security\Algorithm.cs - - - Security\Cryptography\BouncyCastle\asn1\sec\SECNamedCurves.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9Curve.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParameters.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParametersHolder.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECPoint.cs - - - Security\Cryptography\BouncyCastle\crypto\agreement\ECDHCBasicAgreement.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricCipherKeyPair.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricKeyParameter.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\GeneralDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\Sha256Digest.cs - - - Security\Cryptography\BouncyCastle\crypto\generators\ECKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IAsymmetricCipherKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\KeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECDomainParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPrivateKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPublicKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\CryptoApiRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\DigestRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\IRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\util\Pack.cs - - - Security\Cryptography\BouncyCastle\math\BigInteger.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\SimpleBigDecimal.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\Tnaf.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\ZTauElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECAlgorithms.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECCurve.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECFieldElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECLookupTable.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPoint.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPointMap.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\ECEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\GlvEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\LongArray.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\AbstractECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointCombMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\GlvMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\IPreCompCallback.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\PreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ValidityPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafL2RMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\field\FiniteFields.cs - - - Security\Cryptography\BouncyCastle\math\field\GenericPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\GF2Polynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\IFiniteField.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\PrimeField.cs - - - Security\Cryptography\BouncyCastle\math\raw\Mod.cs - - - Security\Cryptography\BouncyCastle\math\raw\Nat.cs - - - Security\Cryptography\BouncyCastle\security\DigestUtilities.cs - - - Security\Cryptography\BouncyCastle\security\SecureRandom.cs - - - Security\Cryptography\BouncyCastle\security\SecurityUtilityException.cs - - - Security\Cryptography\BouncyCastle\util\Arrays.cs - - - Security\Cryptography\BouncyCastle\util\BigIntegers.cs - - - Security\Cryptography\BouncyCastle\util\encoders\Hex.cs - - - Security\Cryptography\BouncyCastle\util\encoders\HexEncoder.cs - - - Security\Cryptography\BouncyCastle\util\IMemoable.cs - - - Security\Cryptography\BouncyCastle\util\Integers.cs - - - Security\Cryptography\BouncyCastle\util\MemoableResetException.cs - - - Security\Cryptography\BouncyCastle\util\Times.cs - - - Security\CertificateHostAlgorithm.cs - - - Security\Cryptography\Chaos.NaCl\CryptoBytes.cs - - - Security\Cryptography\Chaos.NaCl\Ed25519.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array16.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array8.cs - - - Security\Cryptography\Chaos.NaCl\Internal\ByteIntegerConverter.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cmov.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cswap.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_invert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnegative.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnonzero.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul121666.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_neg.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_pow22523.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\FieldElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_double_scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_madd.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_msub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p3.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_cached.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_precomp_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_scalarmult_base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\GroupElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\keypair.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\open.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_clamp.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_mul_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_reduce.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sign.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sqrtm1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\InternalAssert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Poly1305Donna.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\Salsa20.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\SalsaCore.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Sha512Internal.cs - - - Security\Cryptography\Chaos.NaCl\MontgomeryCurve25519.cs - - - Security\Cryptography\Chaos.NaCl\Sha512.cs - - - Security\Cryptography\AsymmetricCipher.cs - - - Security\Cryptography\Bcrypt.cs - - - Security\Cryptography\BlockCipher.cs - - - Security\Cryptography\Cipher.cs - - - Security\Cryptography\CipherDigitalSignature.cs - - - Security\Cryptography\Ciphers\AesCipher.cs - - - Security\Cryptography\Ciphers\Arc4Cipher.cs - - - Security\Cryptography\Ciphers\BlowfishCipher.cs - - - Security\Cryptography\Ciphers\CastCipher.cs - - - Security\Cryptography\Ciphers\CipherMode.cs - - - Security\Cryptography\Ciphers\CipherPadding.cs - - - Security\Cryptography\Ciphers\DesCipher.cs - - - Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs - - - Security\Cryptography\Ciphers\RsaCipher.cs - - - Security\Cryptography\Ciphers\SerpentCipher.cs - - - Security\Cryptography\Ciphers\TripleDesCipher.cs - - - Security\Cryptography\Ciphers\TwofishCipher.cs - - - Security\Cryptography\DigitalSignature.cs - - - Security\Cryptography\DsaDigitalSignature.cs - - - Security\Cryptography\DsaKey.cs - - - Security\Cryptography\ED25519DigitalSignature.cs - - - Security\Cryptography\ED25519Key.cs - - - Security\Cryptography\HMACMD5.cs - - - Security\Cryptography\HMACSHA1.cs - - - Security\Cryptography\HMACSHA256.cs - - - Security\Cryptography\HMACSHA384.cs - - - Security\Cryptography\HMACSHA512.cs - - - Security\Cryptography\Key.cs - - - Security\Cryptography\RsaDigitalSignature.cs - - - Security\Cryptography\RsaKey.cs - - - Security\Cryptography\StreamCipher.cs - - - Security\Cryptography\SymmetricCipher.cs - - - Security\GroupExchangeHashData.cs - - - Security\HostAlgorithm.cs - - - Security\IKeyExchange.cs - - - Security\KeyExchange.cs - - - Security\KeyExchangeDiffieHellman.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha256.cs - - - Security\KeyExchangeDiffieHellmanGroup16Sha512.cs - - - Security\KeyExchangeDiffieHellmanGroup1Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs - - - Security\KeyExchangeDiffieHellmanGroupSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupSha512.cs - - - Security\KeyExchangeDiffieHellmanGroupShaBase.cs - - - Security\KeyExchangeEC.cs - - - Security\KeyExchangeECCurve25519.cs - - - Security\KeyExchangeECDH.cs - - - Security\KeyExchangeECDH256.cs - - - Security\KeyExchangeECDH384.cs - - - Security\KeyExchangeECDH521.cs - - - Security\KeyExchangeHash.cs - - - Security\KeyHostAlgorithm.cs - - - ServiceFactory.cs - - - Session.cs - - - SftpClient.cs - - - ISftpClient.cs - - - Sftp\Flags.cs - - - Sftp\ISftpFileReader.cs - - - Sftp\ISftpResponseFactory.cs - - - Sftp\ISftpSession.cs - - - Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs - - - Sftp\Requests\ExtendedRequests\HardLinkRequest.cs - - - Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs - - - Sftp\Requests\ExtendedRequests\StatVfsRequest.cs - - - Sftp\Requests\SftpBlockRequest.cs - - - Sftp\Requests\SftpCloseRequest.cs - - - Sftp\Requests\SftpExtendedRequest.cs - - - Sftp\Requests\SftpFSetStatRequest.cs - - - Sftp\Requests\SftpFStatRequest.cs - - - Sftp\Requests\SftpInitRequest.cs - - - Sftp\Requests\SftpLinkRequest.cs - - - Sftp\Requests\SftpLStatRequest.cs - - - Sftp\Requests\SftpMkDirRequest.cs - - - Sftp\Requests\SftpOpenDirRequest.cs - - - Sftp\Requests\SftpOpenRequest.cs - - - Sftp\Requests\SftpReadDirRequest.cs - - - Sftp\Requests\SftpReadLinkRequest.cs - - - Sftp\Requests\SftpReadRequest.cs - - - Sftp\Requests\SftpRealPathRequest.cs - - - Sftp\Requests\SftpRemoveRequest.cs - - - Sftp\Requests\SftpRenameRequest.cs - - - Sftp\Requests\SftpRequest.cs - - - Sftp\Requests\SftpRmDirRequest.cs - - - Sftp\Requests\SftpSetStatRequest.cs - - - Sftp\Requests\SftpStatRequest.cs - - - Sftp\Requests\SftpSymLinkRequest.cs - - - Sftp\Requests\SftpUnblockRequest.cs - - - Sftp\Requests\SftpWriteRequest.cs - - - Sftp\Responses\ExtendedReplies\ExtendedReplyInfo.cs - - - Sftp\Responses\ExtendedReplies\StatVfsReplyInfo.cs - - - Sftp\Responses\SftpAttrsResponse.cs - - - Sftp\Responses\SftpDataResponse.cs - - - Sftp\Responses\SftpExtendedReplyResponse.cs - - - Sftp\Responses\SftpHandleResponse.cs - - - Sftp\Responses\SftpNameResponse.cs - - - Sftp\Responses\SftpResponse.cs - - - Sftp\Responses\SftpStatusResponse.cs - - - Sftp\Responses\SftpVersionResponse.cs - - - Sftp\SftpCloseAsyncResult.cs - - - Sftp\SftpDownloadAsyncResult.cs - - - Sftp\SftpFile.cs - - - Sftp\ISftpFile.cs - - - Sftp\SftpFileAttributes.cs - - - Sftp\SftpFileReader.cs - - - Sftp\SftpFileStream.cs - - - Sftp\SftpFileSystemInformation.cs - - - Sftp\SftpListDirectoryAsyncResult.cs - - - Sftp\SftpMessage.cs - - - Sftp\SftpMessageTypes.cs - - - Sftp\SftpOpenAsyncResult.cs - - - Sftp\SftpReadAsyncResult.cs - - - Sftp\SftpRealPathAsyncResult.cs - - - Sftp\SftpResponseFactory.cs - - - Sftp\SftpSession.cs - - - Sftp\SFtpStatAsyncResult.cs - - - Sftp\SftpSynchronizeDirectoriesAsyncResult.cs - - - Sftp\SftpUploadAsyncResult.cs - - - Sftp\StatusCodes.cs - - - Shell.cs - - - ShellStream.cs - - - SshClient.cs - - - SshCommand.cs - - - SshMessageFactory.cs - - - SubsystemSession.cs - - - - Properties\CommonAssemblyInfo.cs - - - - - Designer - - - - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.WindowsPhone/packages.config b/src/Renci.SshNet.WindowsPhone/packages.config deleted file mode 100644 index a9e0cd0e6..000000000 --- a/src/Renci.SshNet.WindowsPhone/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.WindowsPhone8/Properties/AssemblyInfo.cs b/src/Renci.SshNet.WindowsPhone8/Properties/AssemblyInfo.cs deleted file mode 100644 index 3db5746c8..000000000 --- a/src/Renci.SshNet.WindowsPhone8/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SSH.NET Windows Phone 8.0")] -[assembly: Guid("b044a9d9-fe40-4d7e-b198-c142ab9721f0")] - -[assembly: InternalsVisibleTo("Renci.SshNet.Tests")] \ No newline at end of file diff --git a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj b/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj deleted file mode 100644 index fb301e597..000000000 --- a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj +++ /dev/null @@ -1,1496 +0,0 @@ - - - - Debug - AnyCPU - 10.0.20506 - 2.0 - {4A6CA785-1C8A-47FE-98C0-30C675A9328B} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Renci.SshNet - Renci.SshNet - v8.0 - WindowsPhone - false - true - true - 11.0 - - - true - full - false - Bin\Debug - TRACE;DEBUG;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - false - Bin\Debug\Renci.SshNet.xml - true - - - none - true - Bin\Release - TRACE;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - prompt - 4 - false - Bin\Release\Renci.SshNet.xml - - - true - - - true - Bin\x86\Debug - TRACE;DEBUG;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - full - - - prompt - MinimumRecommendedRules.ruleset - false - - - Bin\x86\Release - TRACE;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - pdbonly - - - prompt - MinimumRecommendedRules.ruleset - - - true - Bin\ARM\Debug - TRACE;DEBUG;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - full - - - prompt - MinimumRecommendedRules.ruleset - false - - - Bin\ARM\Release - TRACE;FEATURE_REGEX_COMPILE;FEATURE_RNG_CSP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_DEVICEINFORMATION_APM;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_HASH_SHA1_MANAGED;FEATURE_HASH_SHA256_MANAGED;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256 - true - true - pdbonly - - - prompt - MinimumRecommendedRules.ruleset - - - - Abstractions\CryptoAbstraction.cs - - - Abstractions\DiagnosticAbstraction.cs - - - Abstractions\DnsAbstraction.cs - - - Abstractions\FileSystemAbstraction.cs - - - Abstractions\ReflectionAbstraction.cs - - - Abstractions\SocketAbstraction.cs - - - Abstractions\ThreadAbstraction.cs - - - AuthenticationMethod.cs - - - AuthenticationResult.cs - - - BaseClient.cs - - - Channels\Channel.cs - - - Channels\ChannelDirectTcpip.cs - - - Channels\ChannelForwardedTcpip.cs - - - Channels\ChannelSession.cs - - - Channels\ChannelTypes.cs - - - Channels\ClientChannel.cs - - - Channels\IChannel.cs - - - Channels\IChannelDirectTcpip.cs - - - Channels\IChannelForwardedTcpip.cs - - - Channels\IChannelSession.cs - - - Channels\ServerChannel.cs - - - CipherInfo.cs - - - ClientAuthentication.cs - - - CommandAsyncResult.cs - - - Common\Array.cs - - - Common\ASCIIEncoding.cs - - - Common\AsyncResult.cs - - - Common\AuthenticationBannerEventArgs.cs - - - Common\AuthenticationEventArgs.cs - - - Common\AuthenticationPasswordChangeEventArgs.cs - - - Common\AuthenticationPrompt.cs - - - Common\AuthenticationPromptEventArgs.cs - - - Common\BigInteger.cs - - - Common\ChannelDataEventArgs.cs - - - Common\ChannelEventArgs.cs - - - Common\ChannelExtendedDataEventArgs.cs - - - Common\ChannelOpenConfirmedEventArgs.cs - - - Common\ChannelOpenFailedEventArgs.cs - - - Common\ChannelRequestEventArgs.cs - - - Common\CountdownEvent.cs - - - Common\DerData.cs - - - Common\ExceptionEventArgs.cs - - - Common\Extensions.cs - - - Common\HostKeyEventArgs.cs - - - Common\ObjectIdentifier.cs - - - Common\Pack.cs - - - Common\PacketDump.cs - - - Common\PipeStream.cs - - - Common\PortForwardEventArgs.cs - - - Common\PosixPath.cs - - - Common\ProxyException.cs - - - Common\ScpDownloadEventArgs.cs - - - Common\ScpException.cs - - - Common\ScpUploadEventArgs.cs - - - Common\SemaphoreLight.cs - - - Common\SftpPathNotFoundException.cs - - - Common\SftpPermissionDeniedException.cs - - - Common\ShellDataEventArgs.cs - - - Common\SshAuthenticationException.cs - - - Common\SshConnectionException.cs - - - Common\SshData.cs - - - Common\SshDataStream.cs - - - Common\SshException.cs - - - Common\SshOperationTimeoutException.cs - - - Common\SshPassPhraseNullOrEmptyException.cs - - - Common\TerminalModes.cs - - - Compression\CompressionMode.cs - - - Compression\Compressor.cs - - - Compression\Zlib.cs - - - Compression\ZlibOpenSsh.cs - - - Compression\ZlibStream.cs - - - ConnectionInfo.cs - - - Connection\ConnectorBase.cs - - - Connection\DirectConnector.cs - - - Connection\HttpConnector.cs - - - Connection\IConnector.cs - - - Connection\IProtocolVersionExchange.cs - - - Connection\ISocketFactory.cs - - - Connection\ProtocolVersionExchange.cs - - - Connection\SocketFactory.cs - - - Connection\Socks4Connector.cs - - - Connection\Socks5Connector.cs - - - Connection\SshIdentification.cs - - - ExpectAction.cs - - - ExpectAsyncResult.cs - - - ForwardedPort.cs - - - ForwardedPortDynamic.cs - - - ForwardedPortDynamic.NET.cs - - - ForwardedPortLocal.cs - - - ForwardedPortLocal.NET.cs - - - ForwardedPortRemote.cs - - - ForwardedPortStatus.cs - - - HashInfo.cs - - - IAuthenticationMethod.cs - - - IClientAuthentication.cs - - - IConnectionInfo.cs - - - IForwardedPort.cs - - - IRemotePathTransformation.cs - - - IServiceFactory.cs - - - ISession.cs - - - ISftpClient.cs - - - ISubsystemSession.cs - - - KeyboardInteractiveAuthenticationMethod.cs - - - KeyboardInteractiveConnectionInfo.cs - - - MessageEventArgs.cs - - - Messages\Authentication\BannerMessage.cs - - - Messages\Authentication\FailureMessage.cs - - - Messages\Authentication\InformationRequestMessage.cs - - - Messages\Authentication\InformationResponseMessage.cs - - - Messages\Authentication\PasswordChangeRequiredMessage.cs - - - Messages\Authentication\PublicKeyMessage.cs - - - Messages\Authentication\RequestMessage.cs - - - Messages\Authentication\RequestMessageHost.cs - - - Messages\Authentication\RequestMessageKeyboardInteractive.cs - - - Messages\Authentication\RequestMessageNone.cs - - - Messages\Authentication\RequestMessagePassword.cs - - - Messages\Authentication\RequestMessagePublicKey.cs - - - Messages\Authentication\SuccessMessage.cs - - - Messages\Connection\CancelTcpIpForwardGlobalRequestMessage.cs - - - Messages\Connection\ChannelCloseMessage.cs - - - Messages\Connection\ChannelDataMessage.cs - - - Messages\Connection\ChannelEofMessage.cs - - - Messages\Connection\ChannelExtendedDataMessage.cs - - - Messages\Connection\ChannelFailureMessage.cs - - - Messages\Connection\ChannelMessage.cs - - - Messages\Connection\ChannelOpenConfirmationMessage.cs - - - Messages\Connection\ChannelOpenFailureMessage.cs - - - Messages\Connection\ChannelOpenFailureReasons.cs - - - Messages\Connection\ChannelOpen\ChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\ChannelOpenMessage.cs - - - Messages\Connection\ChannelOpen\DirectTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\ForwardedTcpipChannelInfo.cs - - - Messages\Connection\ChannelOpen\SessionChannelOpenInfo.cs - - - Messages\Connection\ChannelOpen\X11ChannelOpenInfo.cs - - - Messages\Connection\ChannelRequest\BreakRequestInfo.cs - - - Messages\Connection\ChannelRequest\ChannelRequestMessage.cs - - - Messages\Connection\ChannelRequest\EndOfWriteRequestInfo.cs - - - Messages\Connection\ChannelRequest\EnvironmentVariableRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExecRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitSignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\ExitStatusRequestInfo.cs - - - Messages\Connection\ChannelRequest\KeepAliveRequestInfo.cs - - - Messages\Connection\ChannelRequest\PseudoTerminalInfo.cs - - - Messages\Connection\ChannelRequest\RequestInfo.cs - - - Messages\Connection\ChannelRequest\ShellRequestInfo.cs - - - Messages\Connection\ChannelRequest\SignalRequestInfo.cs - - - Messages\Connection\ChannelRequest\SubsystemRequestInfo.cs - - - Messages\Connection\ChannelRequest\WindowChangeRequestInfo.cs - - - Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs - - - Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs - - - Messages\Connection\ChannelSuccessMessage.cs - - - Messages\Connection\ChannelWindowAdjustMessage.cs - - - Messages\Connection\GlobalRequestMessage.cs - - - Messages\Connection\GlobalRequestName.cs - - - Messages\Connection\RequestFailureMessage.cs - - - Messages\Connection\RequestSuccessMessage.cs - - - Messages\Connection\TcpIpForwardGlobalRequestMessage.cs - - - Messages\Message.cs - - - Messages\MessageAttribute.cs - - - Messages\ServiceName.cs - - - Messages\Transport\DebugMessage.cs - - - Messages\Transport\DisconnectMessage.cs - - - Messages\Transport\DisconnectReason.cs - - - Messages\Transport\IgnoreMessage.cs - - - Messages\Transport\IKeyExchangedAllowed.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeGroup.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeInit.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeReply.cs - - - Messages\Transport\KeyExchangeDhGroupExchangeRequest.cs - - - Messages\Transport\KeyExchangeDhInitMessage.cs - - - Messages\Transport\KeyExchangeDhReplyMessage.cs - - - Messages\Transport\KeyExchangeEcdhInitMessage.cs - - - Messages\Transport\KeyExchangeEcdhReplyMessage.cs - - - Messages\Transport\KeyExchangeInitMessage.cs - - - Messages\Transport\NewKeysMessage.cs - - - Messages\Transport\ServiceAcceptMessage.cs - - - Messages\Transport\ServiceRequestMessage.cs - - - Messages\Transport\UnimplementedMessage.cs - - - NoneAuthenticationMethod.cs - - - PasswordAuthenticationMethod.cs - - - PasswordConnectionInfo.cs - - - PrivateKeyAuthenticationMethod.cs - - - PrivateKeyConnectionInfo.cs - - - PrivateKeyFile.cs - - - ProxyTypes.cs - - - RemotePathDoubleQuoteTransformation.cs - - - RemotePathNoneTransformation.cs - - - RemotePathShellQuoteTransformation.cs - - - RemotePathTransformation.cs - - - ScpClient.cs - - - Security\Algorithm.cs - - - Security\Cryptography\BouncyCastle\asn1\sec\SECNamedCurves.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9Curve.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParameters.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECParametersHolder.cs - - - Security\Cryptography\BouncyCastle\asn1\x9\X9ECPoint.cs - - - Security\Cryptography\BouncyCastle\crypto\agreement\ECDHCBasicAgreement.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricCipherKeyPair.cs - - - Security\Cryptography\BouncyCastle\crypto\AsymmetricKeyParameter.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\GeneralDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\digests\Sha256Digest.cs - - - Security\Cryptography\BouncyCastle\crypto\generators\ECKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IAsymmetricCipherKeyPairGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\IDigest.cs - - - Security\Cryptography\BouncyCastle\crypto\KeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECDomainParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyGenerationParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPrivateKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\parameters\ECPublicKeyParameters.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\CryptoApiRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\DigestRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\prng\IRandomGenerator.cs - - - Security\Cryptography\BouncyCastle\crypto\util\Pack.cs - - - Security\Cryptography\BouncyCastle\math\BigInteger.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\SimpleBigDecimal.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\Tnaf.cs - - - Security\Cryptography\BouncyCastle\math\ec\abc\ZTauElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECAlgorithms.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECCurve.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECFieldElement.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECLookupTable.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPoint.cs - - - Security\Cryptography\BouncyCastle\math\ec\ECPointMap.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\ECEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\endo\GlvEndomorphism.cs - - - Security\Cryptography\BouncyCastle\math\ec\LongArray.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\AbstractECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ECMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointCombMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\FixedPointUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\GlvMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\IPreCompCallback.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\PreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\ValidityPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafL2RMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WNafUtilities.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafMultiplier.cs - - - Security\Cryptography\BouncyCastle\math\ec\multiplier\WTauNafPreCompInfo.cs - - - Security\Cryptography\BouncyCastle\math\field\FiniteFields.cs - - - Security\Cryptography\BouncyCastle\math\field\GenericPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\GF2Polynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\IFiniteField.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomial.cs - - - Security\Cryptography\BouncyCastle\math\field\IPolynomialExtensionField.cs - - - Security\Cryptography\BouncyCastle\math\field\PrimeField.cs - - - Security\Cryptography\BouncyCastle\math\raw\Mod.cs - - - Security\Cryptography\BouncyCastle\math\raw\Nat.cs - - - Security\Cryptography\BouncyCastle\security\DigestUtilities.cs - - - Security\Cryptography\BouncyCastle\security\SecureRandom.cs - - - Security\Cryptography\BouncyCastle\security\SecurityUtilityException.cs - - - Security\Cryptography\BouncyCastle\util\Arrays.cs - - - Security\Cryptography\BouncyCastle\util\BigIntegers.cs - - - Security\Cryptography\BouncyCastle\util\encoders\Hex.cs - - - Security\Cryptography\BouncyCastle\util\encoders\HexEncoder.cs - - - Security\Cryptography\BouncyCastle\util\IMemoable.cs - - - Security\Cryptography\BouncyCastle\util\Integers.cs - - - Security\Cryptography\BouncyCastle\util\MemoableResetException.cs - - - Security\Cryptography\BouncyCastle\util\Times.cs - - - Security\CertificateHostAlgorithm.cs - - - Security\Cryptography\Chaos.NaCl\CryptoBytes.cs - - - Security\Cryptography\Chaos.NaCl\Ed25519.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array16.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Array8.cs - - - Security\Cryptography\Chaos.NaCl\Internal\ByteIntegerConverter.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\base2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\d2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cmov.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_cswap.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_invert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnegative.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_isnonzero.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_mul121666.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_neg.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_pow22523.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sq2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\fe_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\FieldElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_double_scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_frombytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_madd.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_msub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p1p1_to_p3.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p2_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_dbl.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_cached.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_p3_to_p2.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_precomp_0.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_scalarmult_base.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_sub.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\ge_tobytes.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\GroupElement.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\keypair.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\open.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\scalarmult.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_clamp.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_mul_add.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sc_reduce.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sign.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Ed25519Ref10\sqrtm1.cs - - - Security\Cryptography\Chaos.NaCl\Internal\InternalAssert.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Poly1305Donna.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\Salsa20.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Salsa\SalsaCore.cs - - - Security\Cryptography\Chaos.NaCl\Internal\Sha512Internal.cs - - - Security\Cryptography\Chaos.NaCl\MontgomeryCurve25519.cs - - - Security\Cryptography\Chaos.NaCl\Sha512.cs - - - Security\Cryptography\AsymmetricCipher.cs - - - Security\Cryptography\Bcrypt.cs - - - Security\Cryptography\BlockCipher.cs - - - Security\Cryptography\Cipher.cs - - - Security\Cryptography\CipherDigitalSignature.cs - - - Security\Cryptography\Ciphers\AesCipher.cs - - - Security\Cryptography\Ciphers\Arc4Cipher.cs - - - Security\Cryptography\Ciphers\BlowfishCipher.cs - - - Security\Cryptography\Ciphers\CastCipher.cs - - - Security\Cryptography\Ciphers\CipherMode.cs - - - Security\Cryptography\Ciphers\CipherPadding.cs - - - Security\Cryptography\Ciphers\DesCipher.cs - - - Security\Cryptography\Ciphers\Modes\CbcCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CfbCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\CtrCipherMode.cs - - - Security\Cryptography\Ciphers\Modes\OfbCipherMode.cs - - - Security\Cryptography\Ciphers\Paddings\PKCS7Padding.cs - - - Security\Cryptography\Ciphers\RsaCipher.cs - - - Security\Cryptography\Ciphers\SerpentCipher.cs - - - Security\Cryptography\Ciphers\TripleDesCipher.cs - - - Security\Cryptography\Ciphers\TwofishCipher.cs - - - Security\Cryptography\DigitalSignature.cs - - - Security\Cryptography\DsaDigitalSignature.cs - - - Security\Cryptography\DsaKey.cs - - - Security\Cryptography\ED25519DigitalSignature.cs - - - Security\Cryptography\ED25519Key.cs - - - Security\Cryptography\HMACMD5.cs - - - Security\Cryptography\HMACSHA1.cs - - - Security\Cryptography\HMACSHA256.cs - - - Security\Cryptography\HMACSHA384.cs - - - Security\Cryptography\HMACSHA512.cs - - - Security\Cryptography\Key.cs - - - Security\Cryptography\EcdsaDigitalSignature.cs - - - Security\Cryptography\EcdsaKey.cs - - - Security\Cryptography\RsaDigitalSignature.cs - - - Security\Cryptography\RsaKey.cs - - - Security\Cryptography\StreamCipher.cs - - - Security\Cryptography\SymmetricCipher.cs - - - Security\GroupExchangeHashData.cs - - - Security\HostAlgorithm.cs - - - Security\IKeyExchange.cs - - - Security\KeyExchange.cs - - - Security\KeyExchangeDiffieHellman.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroup14Sha256.cs - - - Security\KeyExchangeDiffieHellmanGroup16Sha512.cs - - - Security\KeyExchangeDiffieHellmanGroup1Sha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupExchangeShaBase.cs - - - Security\KeyExchangeDiffieHellmanGroupSha1.cs - - - Security\KeyExchangeDiffieHellmanGroupSha256.cs - - - Security\KeyExchangeDiffieHellmanGroupSha512.cs - - - Security\KeyExchangeDiffieHellmanGroupShaBase.cs - - - Security\KeyExchangeEC.cs - - - Security\KeyExchangeECCurve25519.cs - - - Security\KeyExchangeECDH.cs - - - Security\KeyExchangeECDH256.cs - - - Security\KeyExchangeECDH384.cs - - - Security\KeyExchangeECDH521.cs - - - Security\KeyExchangeHash.cs - - - Security\KeyHostAlgorithm.cs - - - ServiceFactory.cs - - - Session.cs - - - SftpClient.cs - - - Sftp\Flags.cs - - - Sftp\ISftpFileReader.cs - - - Sftp\ISftpResponseFactory.cs - - - Sftp\ISftpSession.cs - - - Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs - - - Sftp\Requests\ExtendedRequests\HardLinkRequest.cs - - - Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs - - - Sftp\Requests\ExtendedRequests\StatVfsRequest.cs - - - Sftp\Requests\SftpBlockRequest.cs - - - Sftp\Requests\SftpCloseRequest.cs - - - Sftp\Requests\SftpExtendedRequest.cs - - - Sftp\Requests\SftpFSetStatRequest.cs - - - Sftp\Requests\SftpFStatRequest.cs - - - Sftp\Requests\SftpInitRequest.cs - - - Sftp\Requests\SftpLinkRequest.cs - - - Sftp\Requests\SftpLStatRequest.cs - - - Sftp\Requests\SftpMkDirRequest.cs - - - Sftp\Requests\SftpOpenDirRequest.cs - - - Sftp\Requests\SftpOpenRequest.cs - - - Sftp\Requests\SftpReadDirRequest.cs - - - Sftp\Requests\SftpReadLinkRequest.cs - - - Sftp\Requests\SftpReadRequest.cs - - - Sftp\Requests\SftpRealPathRequest.cs - - - Sftp\Requests\SftpRemoveRequest.cs - - - Sftp\Requests\SftpRenameRequest.cs - - - Sftp\Requests\SftpRequest.cs - - - Sftp\Requests\SftpRmDirRequest.cs - - - Sftp\Requests\SftpSetStatRequest.cs - - - Sftp\Requests\SftpStatRequest.cs - - - Sftp\Requests\SftpSymLinkRequest.cs - - - Sftp\Requests\SftpUnblockRequest.cs - - - Sftp\Requests\SftpWriteRequest.cs - - - Sftp\Responses\ExtendedReplies\ExtendedReplyInfo.cs - - - Sftp\Responses\ExtendedReplies\StatVfsReplyInfo.cs - - - Sftp\Responses\SftpAttrsResponse.cs - - - Sftp\Responses\SftpDataResponse.cs - - - Sftp\Responses\SftpExtendedReplyResponse.cs - - - Sftp\Responses\SftpHandleResponse.cs - - - Sftp\Responses\SftpNameResponse.cs - - - Sftp\Responses\SftpResponse.cs - - - Sftp\Responses\SftpStatusResponse.cs - - - Sftp\Responses\SftpVersionResponse.cs - - - Sftp\SftpCloseAsyncResult.cs - - - Sftp\SftpDownloadAsyncResult.cs - - - Sftp\SftpFile.cs - - - Sftp\ISftpFile.cs - - - Sftp\SftpFileAttributes.cs - - - Sftp\SftpFileReader.cs - - - Sftp\SftpFileStream.cs - - - Sftp\SftpFileSystemInformation.cs - - - Sftp\SftpListDirectoryAsyncResult.cs - - - Sftp\SftpMessage.cs - - - Sftp\SftpMessageTypes.cs - - - Sftp\SftpOpenAsyncResult.cs - - - Sftp\SftpReadAsyncResult.cs - - - Sftp\SftpRealPathAsyncResult.cs - - - Sftp\SftpResponseFactory.cs - - - Sftp\SftpSession.cs - - - Sftp\SFtpStatAsyncResult.cs - - - Sftp\SftpSynchronizeDirectoriesAsyncResult.cs - - - Sftp\SftpUploadAsyncResult.cs - - - Sftp\StatusCodes.cs - - - Shell.cs - - - ShellStream.cs - - - SshClient.cs - - - SshCommand.cs - - - SshMessageFactory.cs - - - SubsystemSession.cs - - - - Properties\CommonAssemblyInfo.cs - - - - - - - - ..\..\packages\SshNet.Security.Cryptography.1.2.0\lib\wp8\SshNet.Security.Cryptography.dll - True - - - - - - - - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.WindowsPhone8/packages.config b/src/Renci.SshNet.WindowsPhone8/packages.config deleted file mode 100644 index a571ea4f4..000000000 --- a/src/Renci.SshNet.WindowsPhone8/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/Renci.SshNet.VS2019.sln b/src/Renci.SshNet.sln similarity index 100% rename from src/Renci.SshNet.VS2019.sln rename to src/Renci.SshNet.sln diff --git a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs index 2029b0143..e358767a1 100644 --- a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs @@ -63,9 +63,9 @@ public static void Connect(Socket socket, IPEndPoint remoteEndpoint, TimeSpan co } #if FEATURE_TAP - public static Task ConnectAsync(Socket socket, IPEndPoint remoteEndpoint, CancellationToken cancellationToken) + public static async Task ConnectAsync(Socket socket, IPEndPoint remoteEndpoint, CancellationToken cancellationToken) { - return socket.ConnectAsync(remoteEndpoint, cancellationToken); + await socket.ConnectAsync(remoteEndpoint, cancellationToken).ConfigureAwait(false); } #endif diff --git a/src/Renci.SshNet/ForwardedPortDynamic.NET.cs b/src/Renci.SshNet/ForwardedPortDynamic.NET.cs index 36a804558..31b3a0ab9 100644 --- a/src/Renci.SshNet/ForwardedPortDynamic.NET.cs +++ b/src/Renci.SshNet/ForwardedPortDynamic.NET.cs @@ -204,10 +204,19 @@ private bool HandleSocks(IChannelDirectTcpip channel, Socket clientSocket, TimeS { // ignore exception thrown by interrupting the blocking receive as part of closing // the forwarded port +#if NETFRAMEWORK if (ex.SocketErrorCode != SocketError.Interrupted) { RaiseExceptionEvent(ex); } +#else + // Since .NET 5 the exception has been changed. + // more info https://github.com/dotnet/runtime/issues/41585 + if (ex.SocketErrorCode != SocketError.ConnectionAborted) + { + RaiseExceptionEvent(ex); + } +#endif return false; } finally diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index 740ec7ee1..d9399877b 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -7,44 +7,18 @@ ../Renci.SshNet.snk 6 true - net35;net40;net472;netstandard1.3;netstandard2.0 + net462;netstandard2.0;net6.0;net7.0 - - + - - - - - - - - - - - - - - FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_POLL;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA - - - FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA - - - FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA;FEATURE_TAP - - - FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_REFLECTION_TYPEINFO;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_TAP;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_TAP - - + FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_ECDSA;FEATURE_TAP diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml b/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml deleted file mode 100644 index 0ce734075..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml.cs b/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml.cs deleted file mode 100644 index 771bdf257..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/App.xaml.cs +++ /dev/null @@ -1,222 +0,0 @@ -using System; -using System.Diagnostics; -using System.Windows; -using System.Windows.Markup; -using System.Windows.Navigation; -using Microsoft.Phone.Controls; -using Microsoft.Phone.Shell; -using Renci.SshNet.Tests.Resources; - -namespace Renci.SshNet.Tests -{ - public partial class App : Application - { - /// - /// Provides easy access to the root frame of the Phone Application. - /// - /// The root frame of the Phone Application. - public static PhoneApplicationFrame RootFrame { get; private set; } - - /// - /// Constructor for the Application object. - /// - public App() - { - // Global handler for uncaught exceptions. - UnhandledException += Application_UnhandledException; - - // Standard XAML initialization - InitializeComponent(); - - // Phone-specific initialization - InitializePhoneApplication(); - - // Language display initialization - InitializeLanguage(); - - // Show graphics profiling information while debugging. - if (Debugger.IsAttached) - { - // Display the current frame rate counters. - Application.Current.Host.Settings.EnableFrameRateCounter = true; - - // Show the areas of the app that are being redrawn in each frame. - //Application.Current.Host.Settings.EnableRedrawRegions = true; - - // Enable non-production analysis visualization mode, - // which shows areas of a page that are handed off to GPU with a colored overlay. - //Application.Current.Host.Settings.EnableCacheVisualization = true; - - // Prevent the screen from turning off while under the debugger by disabling - // the application's idle detection. - // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run - // and consume battery power when the user is not using the phone. - PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled; - } - - } - - // Code to execute when the application is launching (eg, from Start) - // This code will not execute when the application is reactivated - private void Application_Launching(object sender, LaunchingEventArgs e) - { - } - - // Code to execute when the application is activated (brought to foreground) - // This code will not execute when the application is first launched - private void Application_Activated(object sender, ActivatedEventArgs e) - { - } - - // Code to execute when the application is deactivated (sent to background) - // This code will not execute when the application is closing - private void Application_Deactivated(object sender, DeactivatedEventArgs e) - { - } - - // Code to execute when the application is closing (eg, user hit Back) - // This code will not execute when the application is deactivated - private void Application_Closing(object sender, ClosingEventArgs e) - { - } - - // Code to execute if a navigation fails - private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e) - { - if (Debugger.IsAttached) - { - // A navigation has failed; break into the debugger - Debugger.Break(); - } - } - - // Code to execute on Unhandled Exceptions - private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) - { - if (Debugger.IsAttached) - { - // An unhandled exception has occurred; break into the debugger - Debugger.Break(); - } - } - - #region Phone application initialization - - // Avoid double-initialization - private bool phoneApplicationInitialized = false; - - // Do not add any additional code to this method - private void InitializePhoneApplication() - { - if (phoneApplicationInitialized) - return; - - // Create the frame but don't set it as RootVisual yet; this allows the splash - // screen to remain active until the application is ready to render. - RootFrame = new PhoneApplicationFrame(); - RootFrame.Navigated += CompleteInitializePhoneApplication; - - // Handle navigation failures - RootFrame.NavigationFailed += RootFrame_NavigationFailed; - - // Handle reset requests for clearing the backstack - RootFrame.Navigated += CheckForResetNavigation; - - // Ensure we don't initialize again - phoneApplicationInitialized = true; - } - - // Do not add any additional code to this method - private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e) - { - // Set the root visual to allow the application to render - if (RootVisual != RootFrame) - RootVisual = RootFrame; - - // Remove this handler since it is no longer needed - RootFrame.Navigated -= CompleteInitializePhoneApplication; - } - - private void CheckForResetNavigation(object sender, NavigationEventArgs e) - { - // If the app has received a 'reset' navigation, then we need to check - // on the next navigation to see if the page stack should be reset - if (e.NavigationMode == NavigationMode.Reset) - RootFrame.Navigated += ClearBackStackAfterReset; - } - - private void ClearBackStackAfterReset(object sender, NavigationEventArgs e) - { - // Unregister the event so it doesn't get called again - RootFrame.Navigated -= ClearBackStackAfterReset; - - // Only clear the stack for 'new' (forward) and 'refresh' navigations - if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh) - return; - - // For UI consistency, clear the entire page stack - while (RootFrame.RemoveBackEntry() != null) - { - ; // do nothing - } - } - - #endregion - - // Initialize the app's font and flow direction as defined in its localized resource strings. - // - // To ensure that the font of your application is aligned with its supported languages and that the - // FlowDirection for each of those languages follows its traditional direction, ResourceLanguage - // and ResourceFlowDirection should be initialized in each resx file to match these values with that - // file's culture. For example: - // - // AppResources.es-ES.resx - // ResourceLanguage's value should be "es-ES" - // ResourceFlowDirection's value should be "LeftToRight" - // - // AppResources.ar-SA.resx - // ResourceLanguage's value should be "ar-SA" - // ResourceFlowDirection's value should be "RightToLeft" - // - // For more info on localizing Windows Phone apps see http://go.microsoft.com/fwlink/?LinkId=262072. - // - private void InitializeLanguage() - { - try - { - // Set the font to match the display language defined by the - // ResourceLanguage resource string for each supported language. - // - // Fall back to the font of the neutral language if the Display - // language of the phone is not supported. - // - // If a compiler error is hit then ResourceLanguage is missing from - // the resource file. - RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage); - - // Set the FlowDirection of all elements under the root frame based - // on the ResourceFlowDirection resource string for each - // supported language. - // - // If a compiler error is hit then ResourceFlowDirection is missing from - // the resource file. - FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection); - RootFrame.FlowDirection = flow; - } - catch - { - // If an exception is caught here it is most likely due to either - // ResourceLangauge not being correctly set to a supported language - // code or ResourceFlowDirection is set to a value other than LeftToRight - // or RightToLeft. - - if (Debugger.IsAttached) - { - Debugger.Break(); - } - - throw; - } - } - } -} \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Assets/AlignmentGrid.png b/test/Renci.SshNet.WindowsPhone8.Tests/Assets/AlignmentGrid.png deleted file mode 100644 index f7d2e97804e451530960b57429a2b0a26c86f5d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9042 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 IP1{HR1(GMkF8}}l diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Assets/Tiles/FlipCycleTileMedium.png b/test/Renci.SshNet.WindowsPhone8.Tests/Assets/Tiles/FlipCycleTileMedium.png deleted file mode 100644 index e93b89d600641c9d5b05f94493a9fde6afa850e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9070 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 - /// Provides access to string resources. - /// - public class LocalizedStrings - { - private static readonly AppResources _localizedResources = new AppResources(); - - public AppResources LocalizedResources { get { return _localizedResources; } } - } -} \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml b/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml deleted file mode 100644 index 4da3c91e9..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml.cs b/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml.cs deleted file mode 100644 index ce08790e6..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/MainPage.xaml.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Threading; -using Microsoft.Phone.Controls; -using Microsoft.VisualStudio.TestPlatform.Core; -using Microsoft.VisualStudio.TestPlatform.TestExecutor; -using vstest_executionengine_platformbridge; - -namespace Renci.SshNet.Tests -{ - public partial class MainPage : PhoneApplicationPage - { - // Constructor - public MainPage() - { - InitializeComponent(); - - var wrapper = new TestExecutorServiceWrapper(); - new Thread(new ServiceMain((param0, param1) => wrapper.SendMessage((ContractName)param0, param1)).Run).Start(); - - } - } -} \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AppManifest.xml b/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AppManifest.xml deleted file mode 100644 index 6712a1178..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AppManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AssemblyInfo.cs b/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index c9bbc102f..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Resources; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Renci.SshNet.WindowsPhone8.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Renci.SshNet.WindowsPhone8.Tests")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("911d635c-6e0e-46e8-9e8b-99bfb1790991")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/WMAppManifest.xml b/test/Renci.SshNet.WindowsPhone8.Tests/Properties/WMAppManifest.xml deleted file mode 100644 index 1590bfd8f..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Properties/WMAppManifest.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - Assets\ApplicationIcon.png - - - - - - - - - - - - - - Assets\Tiles\FlipCycleTileSmall.png - 0 - Assets\Tiles\FlipCycleTileMedium.png - Renci.SshNet.WindowsPhone8.Tests - - - - - - - - - - - vstest_executionengine_platformbridge.dll - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Renci.SshNet.WindowsPhone8.Tests.csproj b/test/Renci.SshNet.WindowsPhone8.Tests/Renci.SshNet.WindowsPhone8.Tests.csproj deleted file mode 100644 index 212e28403..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Renci.SshNet.WindowsPhone8.Tests.csproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - Debug - x86 - 10.0.20506 - 2.0 - {26F0D644-B3EF-47DF-8040-E9E4B2E63884} - {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - Renci.SshNet.Tests - Renci.SshNet.Tests - WindowsPhone - v8.0 - $(TargetFrameworkVersion) - true - true - - - true - true - Renci.SshNet.WindowsPhone8.Tests_$(Configuration)_$(Platform).xap - Properties\AppManifest.xml - Renci.SshNet.WindowsPhone8.Tests.App - false - 11.0 - true - - - true - full - false - Bin\x86\Debug - TRACE;DEBUG;SILVERLIGHT - true - true - prompt - 4 - - - pdbonly - true - Bin\x86\Release - TRACE;SILVERLIGHT;WINDOWS_PHONE - true - true - prompt - 4 - - - true - full - false - Bin\ARM\Debug - DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE - true - true - prompt - 4 - - - pdbonly - true - Bin\ARM\Release - TRACE;SILVERLIGHT;WINDOWS_PHONE - true - true - prompt - 4 - - - - App.xaml - - - - MainPage.xaml - - - - True - True - AppResources.resx - - - - - Designer - MSBuild:Compile - - - Designer - MSBuild:Compile - - - - - - Designer - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - PublicResXFileCodeGenerator - AppResources.Designer.cs - - - - - - - - {4a6ca785-1c8a-47fe-98c0-30c675a9328b} - Renci.SshNet.WindowsPhone8 - - - - - - - - \ No newline at end of file diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.Designer.cs b/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.Designer.cs deleted file mode 100644 index d4a8eaf71..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.Designer.cs +++ /dev/null @@ -1,108 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Renci.SshNet.Tests.Resources { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - public class AppResources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal AppResources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Renci.SshNet.Tests.Resources.AppResources", typeof(AppResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - public static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to add. - /// - public static string AppBarButtonText { - get { - return ResourceManager.GetString("AppBarButtonText", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Menu Item. - /// - public static string AppBarMenuItemText { - get { - return ResourceManager.GetString("AppBarMenuItemText", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MY APPLICATION. - /// - public static string ApplicationTitle { - get { - return ResourceManager.GetString("ApplicationTitle", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to LeftToRight. - /// - public static string ResourceFlowDirection { - get { - return ResourceManager.GetString("ResourceFlowDirection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to en-US. - /// - public static string ResourceLanguage { - get { - return ResourceManager.GetString("ResourceLanguage", resourceCulture); - } - } - } -} diff --git a/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.resx b/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.resx deleted file mode 100644 index 529a19431..000000000 --- a/test/Renci.SshNet.WindowsPhone8.Tests/Resources/AppResources.resx +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - LeftToRight - Controls the FlowDirection for all elements in the RootFrame. Set to the traditional direction of this resource file's language - - - en-US - Controls the Language and ensures that the font for all elements in the RootFrame aligns with the app's language. Set to the language code of this resource file's language. - - - MY APPLICATION - - - add - - - Menu Item - - \ No newline at end of file From 8c932fb1e85760864393c2ed72e078a5bd8ddd9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Nag=C3=B3rski?= Date: Tue, 9 May 2023 21:21:13 +0200 Subject: [PATCH 18/19] Remove old features [Part 1] (#1117) Remove obsolete feature switches (now that we've remove support for legacy target frameworks) and remove corresponding conditional code. --- ...pose_SessionIsConnectedAndChannelIsOpen.cs | 3 - .../Classes/Common/CountdownEventTest.cs | 3 - .../CountdownEventTest_Dispose_NotSet.cs | 4 - .../Common/CountdownEventTest_Dispose_Set.cs | 4 - .../Sftp/SftpFileStreamAsyncTestBase.cs | 4 +- ...eStreamTest_OpenAsync_FileAccessInvalid.cs | 4 +- ...OpenAsync_FileModeAppend_FileAccessRead.cs | 4 +- ...sync_FileModeAppend_FileAccessReadWrite.cs | 4 +- ...penAsync_FileModeAppend_FileAccessWrite.cs | 4 +- ...nAsync_FileModeCreateNew_FileAccessRead.cs | 4 +- ...c_FileModeCreateNew_FileAccessReadWrite.cs | 4 +- ...Async_FileModeCreateNew_FileAccessWrite.cs | 4 +- ...OpenAsync_FileModeCreate_FileAccessRead.cs | 4 +- ...te_FileAccessReadWrite_FileDoesNotExist.cs | 4 +- ...deCreate_FileAccessReadWrite_FileExists.cs | 4 +- ...Create_FileAccessWrite_FileDoesNotExist.cs | 6 +- ...leModeCreate_FileAccessWrite_FileExists.cs | 6 +- ...ileStreamTest_OpenAsync_FileModeInvalid.cs | 4 +- ...ync_FileModeOpenOrCreate_FileAccessRead.cs | 6 +- ...ileModeOpenOrCreate_FileAccessReadWrite.cs | 4 +- ...nc_FileModeOpenOrCreate_FileAccessWrite.cs | 4 +- ...t_OpenAsync_FileModeOpen_FileAccessRead.cs | 4 +- ...nAsync_FileModeOpen_FileAccessReadWrite.cs | 4 +- ..._OpenAsync_FileModeOpen_FileAccessWrite.cs | 4 +- ...enAsync_FileModeTruncate_FileAccessRead.cs | 4 +- ...nc_FileModeTruncate_FileAccessReadWrite.cs | 4 +- ...nAsync_FileModeTruncate_FileAccessWrite.cs | 6 +- ...FromServerThanCountAndEqualToBufferSize.cs | 6 +- ...romServerThanCountAndLessThanBufferSize.cs | 4 +- ...fferAndReadMoreBytesFromServerThanCount.cs | 4 +- ...tGreatherThanTwoTimesTheWriteBufferSize.cs | 4 +- .../Classes/SftpClientTest.ConnectAsync.cs | 6 +- .../Classes/SftpClientTest.DeleteFileAsync.cs | 6 +- .../Classes/SftpClientTest.RenameFileAsync.cs | 4 +- .../Common/AsyncSocketListener.cs | 3 - .../Renci.SshNet.Tests.csproj | 2 +- .../Abstractions/CryptoAbstraction.cs | 129 ------- .../Abstractions/DiagnosticAbstraction.cs | 7 - .../Abstractions/DnsAbstraction.cs | 6 - .../Abstractions/ReflectionAbstraction.cs | 8 - .../Abstractions/SocketAbstraction.cs | 361 +----------------- .../Abstractions/SocketExtensions.cs | 4 +- .../Abstractions/ThreadAbstraction.cs | 19 - src/Renci.SshNet/BaseClient.cs | 7 +- src/Renci.SshNet/Common/ASCIIEncoding.cs | 167 -------- src/Renci.SshNet/Common/CountdownEvent.cs | 171 --------- src/Renci.SshNet/Common/Extensions.cs | 60 --- src/Renci.SshNet/Common/PacketDump.cs | 8 +- src/Renci.SshNet/Common/SshData.cs | 5 +- src/Renci.SshNet/Common/SshDataStream.cs | 6 - src/Renci.SshNet/Connection/ConnectorBase.cs | 7 - .../Connection/DirectConnector.cs | 2 - src/Renci.SshNet/Connection/IConnector.cs | 2 - .../Connection/IProtocolVersionExchange.cs | 2 - .../Connection/ProtocolVersionExchange.cs | 11 - src/Renci.SshNet/Connection/ProxyConnector.cs | 12 +- .../Connection/Socks4Connector.cs | 4 - src/Renci.SshNet/ConnectionInfo.cs | 2 - src/Renci.SshNet/IBaseClient.cs | 4 - src/Renci.SshNet/ISession.cs | 4 - src/Renci.SshNet/ISftpClient.cs | 13 - src/Renci.SshNet/NoneAuthenticationMethod.cs | 3 - src/Renci.SshNet/PrivateKeyFile.cs | 9 +- src/Renci.SshNet/Renci.SshNet.csproj | 4 +- .../crypto/prng/CryptoApiRandomGenerator.cs | 10 - .../Security/Cryptography/Bcrypt.cs | 8 +- .../Cryptography/EcdsaDigitalSignature.cs | 4 +- .../Security/Cryptography/EcdsaKey.cs | 4 +- .../Security/Cryptography/HMACMD5.cs | 6 +- .../Security/Cryptography/HMACSHA1.cs | 6 +- .../Security/Cryptography/HMACSHA256.cs | 6 +- .../Security/Cryptography/HMACSHA384.cs | 6 +- .../Security/Cryptography/HMACSHA512.cs | 6 +- src/Renci.SshNet/Session.cs | 67 ---- src/Renci.SshNet/Sftp/ISftpSession.cs | 24 -- src/Renci.SshNet/Sftp/SftpFileStream.cs | 13 +- src/Renci.SshNet/Sftp/SftpSession.cs | 31 -- src/Renci.SshNet/SftpClient.cs | 14 - src/Renci.SshNet/Shell.cs | 18 - 79 files changed, 60 insertions(+), 1353 deletions(-) delete mode 100644 src/Renci.SshNet/Common/ASCIIEncoding.cs delete mode 100644 src/Renci.SshNet/Common/CountdownEvent.cs diff --git a/src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs b/src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs index a75d407d3..da7739694 100644 --- a/src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs +++ b/src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs @@ -5,9 +5,6 @@ using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; -#if !FEATURE_SOCKET_DISPOSE -using Renci.SshNet.Common; -#endif // !FEATURE_SOCKET_DISPOSE using Renci.SshNet.Channels; using Renci.SshNet.Messages.Connection; using Renci.SshNet.Tests.Common; diff --git a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs index 6954beb14..6ab52acef 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest.cs @@ -2,9 +2,6 @@ using System.Diagnostics; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; -#if !FEATURE_THREAD_COUNTDOWNEVENT -using CountdownEvent = Renci.SshNet.Common.CountdownEvent; -#endif namespace Renci.SshNet.Tests.Classes.Common { diff --git a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_NotSet.cs b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_NotSet.cs index 3d5a5d17d..a2badf97e 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_NotSet.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_NotSet.cs @@ -1,10 +1,6 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -#if !FEATURE_THREAD_COUNTDOWNEVENT -using CountdownEvent = Renci.SshNet.Common.CountdownEvent; -#else using System.Threading; -#endif namespace Renci.SshNet.Tests.Classes.Common { diff --git a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_Set.cs b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_Set.cs index 60f13c302..df5f5b979 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_Set.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/CountdownEventTest_Dispose_Set.cs @@ -1,10 +1,6 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; -#if !FEATURE_THREAD_COUNTDOWNEVENT -using CountdownEvent = Renci.SshNet.Common.CountdownEvent; -#else using System.Threading; -#endif namespace Renci.SshNet.Tests.Classes.Common { diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs index b8b7b4ae9..110a20bed 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamAsyncTestBase.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -66,4 +65,3 @@ protected byte[] GenerateRandom(uint length, Random random) } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs index fab12dad6..4febea075 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileAccessInvalid.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -54,4 +53,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs index 0ffeaeb6c..14a2338b0 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -55,4 +54,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs index 2ed8cd14f..c58f33873 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessReadWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -55,4 +54,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs index 8d9bc960b..a95be4233 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeAppend_FileAccessWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -152,4 +151,3 @@ public void RequestFStatOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs index eb83af777..a697a3c53 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -55,4 +54,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs index 5c2318086..c1b271dd3 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessReadWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs index 7671fe300..b6c6487df 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreateNew_FileAccessWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs index 2c6d28a6e..460081fca 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -55,4 +54,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs index 5fe519f17..9563b9fcd 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileDoesNotExist.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs index a313afb96..e2d5d061c 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessReadWrite_FileExists.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs index c1d7fc960..aa29b7397 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileDoesNotExist.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -132,5 +131,4 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnceWithTruncateAndOnceWithCr SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs index 834299706..ed001ab2a 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeCreate_FileAccessWrite_FileExists.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -132,5 +131,4 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, _cancellationToken), Times.Once); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs index 9cfc4a37f..075967ac2 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeInvalid.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -54,4 +53,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs index f9360c40c..15a40915a 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -137,5 +136,4 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Read | Flags.CreateNewOrOpen, _cancellationToken), Times.Once); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs index 7e5e4d867..c7cd5d4a4 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessReadWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs index edccf9b99..0b69f581e 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpenOrCreate_FileAccessWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs index 1d4f686fa..76387888f 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -139,4 +138,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs index 8ee641337..56589f668 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessReadWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs index 4be281731..db61a2a6e 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeOpen_FileAccessWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs index 9883a5a76..9247274e8 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessRead.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -56,4 +55,3 @@ public void CtorShouldHaveThrownArgumentException() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs index 2d0efd24f..ecde02148 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessReadWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -133,4 +132,3 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs index 5f61e1984..0c06eba6a 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_OpenAsync_FileModeTruncate_FileAccessWrite.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -132,5 +131,4 @@ public void RequestOpenOnSftpSessionShouldBeInvokedOnce() SftpSessionMock.Verify(p => p.RequestOpenAsync(_path, Flags.Write | Flags.Truncate, _cancellationToken), Times.Once); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs index 13f3e1255..d3b5983be 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndEqualToBufferSize.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -155,5 +154,4 @@ public async Task ReadShouldReturnAllRemaningBytesFromReadBufferAndReadAgainWhen SftpSessionMock.Verify(p => p.RequestReadAsync(_handle, (ulong)(_serverData1Length + _serverData2Length), _readBufferSize, default)); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs index 2da0a4385..29121639c 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadLessBytesFromServerThanCountAndLessThanBufferSize.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -149,4 +148,3 @@ public async Task SubsequentReadShouldReadAgainFromCurrentPositionFromServerAndN } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs index 80895217e..d95ffd0a0 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_ReadAsync_ReadMode_NoDataInReaderBufferAndReadMoreBytesFromServerThanCount.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -140,4 +139,3 @@ public async Task SubsequentReadShouldReturnAllRemaningBytesFromReadBufferAndRea } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs index dcbfedf63..a9f4587b0 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_WriteAsync_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.Globalization; using System.IO; using System.Threading; @@ -140,4 +139,3 @@ public async Task FlushShouldFlushBuffer() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs index 75602ea2c..df7a8f0b6 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.ConnectAsync.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.Net.Sockets; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -44,5 +43,4 @@ public async Task ConnectAsync_ProxyHostNameInvalid_ShouldThrowSocketExceptionWi } } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs index 20e68e812..9d8464377 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.DeleteFileAsync.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Tests.Properties; using System; using System.Threading.Tasks; @@ -23,5 +22,4 @@ public async Task Test_Sftp_DeleteFileAsync_Null() } } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs index 38d651f97..a24ec0942 100644 --- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs +++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.RenameFileAsync.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Tests.Properties; using System; using System.IO; @@ -63,4 +62,3 @@ public async Task Test_Sftp_RenameFileAsync_Null() } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs index 8fa81a301..78319f76f 100644 --- a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs +++ b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs @@ -3,9 +3,6 @@ using System.Net; using System.Net.Sockets; using System.Threading; -#if !FEATURE_SOCKET_DISPOSE -using Renci.SshNet.Common; -#endif // !FEATURE_SOCKET_DISPOSE namespace Renci.SshNet.Tests.Common { diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index b577179e2..80c36aa70 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -7,7 +7,7 @@ - FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_TPL;FEATURE_TAP + FEATURE_TPL diff --git a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs index ff9e50a52..2c7d38b0c 100644 --- a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs @@ -5,9 +5,7 @@ namespace Renci.SshNet.Abstractions { internal static class CryptoAbstraction { -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP private static readonly System.Security.Cryptography.RandomNumberGenerator Randomizer = CreateRandomNumberGenerator(); -#endif /// /// Generates a array of the specified length, and fills it with a @@ -31,105 +29,38 @@ public static byte[] GenerateRandom(int length) /// public static void GenerateRandom(byte[] data) { -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP Randomizer.GetBytes(data); -#else - if(data == null) - throw new ArgumentNullException("data"); - - var buffer = Windows.Security.Cryptography.CryptographicBuffer.GenerateRandom((uint) data.Length); - System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.CopyTo(buffer, data); -#endif } -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP public static System.Security.Cryptography.RandomNumberGenerator CreateRandomNumberGenerator() { -#if FEATURE_RNG_CREATE return System.Security.Cryptography.RandomNumberGenerator.Create(); -#elif FEATURE_RNG_CSP - return new System.Security.Cryptography.RNGCryptoServiceProvider(); -#else -#error Creation of RandomNumberGenerator is not implemented. -#endif } -#endif // FEATURE_RNG_CREATE || FEATURE_RNG_CSP -#if FEATURE_HASH_MD5 public static System.Security.Cryptography.MD5 CreateMD5() { return System.Security.Cryptography.MD5.Create(); } -#else - public static global::SshNet.Security.Cryptography.MD5 CreateMD5() - { - return new global::SshNet.Security.Cryptography.MD5(); - } -#endif // FEATURE_HASH_MD5 -#if FEATURE_HASH_SHA1_CREATE || FEATURE_HASH_SHA1_MANAGED public static System.Security.Cryptography.SHA1 CreateSHA1() { -#if FEATURE_HASH_SHA1_CREATE return System.Security.Cryptography.SHA1.Create(); -#elif FEATURE_HASH_SHA1_MANAGED - return new System.Security.Cryptography.SHA1Managed(); -#endif } -#else - public static global::SshNet.Security.Cryptography.SHA1 CreateSHA1() - { - return new global::SshNet.Security.Cryptography.SHA1(); - } -#endif -#if FEATURE_HASH_SHA256_CREATE || FEATURE_HASH_SHA256_MANAGED public static System.Security.Cryptography.SHA256 CreateSHA256() { -#if FEATURE_HASH_SHA256_CREATE return System.Security.Cryptography.SHA256.Create(); -#elif FEATURE_HASH_SHA256_MANAGED - return new System.Security.Cryptography.SHA256Managed(); -#endif } -#else - public static global::SshNet.Security.Cryptography.SHA256 CreateSHA256() - { - return new global::SshNet.Security.Cryptography.SHA256(); - } -#endif -#if FEATURE_HASH_SHA384_CREATE || FEATURE_HASH_SHA384_MANAGED public static System.Security.Cryptography.SHA384 CreateSHA384() { -#if FEATURE_HASH_SHA384_CREATE return System.Security.Cryptography.SHA384.Create(); -#elif FEATURE_HASH_SHA384_MANAGED - return new System.Security.Cryptography.SHA384Managed(); -#endif - } -#else - public static global::SshNet.Security.Cryptography.SHA384 CreateSHA384() - { - return new global::SshNet.Security.Cryptography.SHA384(); } -#endif -#if FEATURE_HASH_SHA512_CREATE || FEATURE_HASH_SHA512_MANAGED public static System.Security.Cryptography.SHA512 CreateSHA512() { -#if FEATURE_HASH_SHA512_CREATE return System.Security.Cryptography.SHA512.Create(); -#elif FEATURE_HASH_SHA512_MANAGED - return new System.Security.Cryptography.SHA512Managed(); -#endif } -#else - public static global::SshNet.Security.Cryptography.SHA512 CreateSHA512() - { - return new global::SshNet.Security.Cryptography.SHA512(); - } -#endif #if FEATURE_HASH_RIPEMD160_CREATE || FEATURE_HASH_RIPEMD160_MANAGED public static System.Security.Cryptography.RIPEMD160 CreateRIPEMD160() @@ -147,7 +78,6 @@ public static System.Security.Cryptography.RIPEMD160 CreateRIPEMD160() } #endif // FEATURE_HASH_RIPEMD160 -#if FEATURE_HMAC_MD5 public static System.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key) { return new System.Security.Cryptography.HMACMD5(key); @@ -157,19 +87,7 @@ public static HMACMD5 CreateHMACMD5(byte[] key, int hashSize) { return new HMACMD5(key, hashSize); } -#else - public static global::SshNet.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key) - { - return new global::SshNet.Security.Cryptography.HMACMD5(key); - } - - public static global::SshNet.Security.Cryptography.HMACMD5 CreateHMACMD5(byte[] key, int hashSize) - { - return new global::SshNet.Security.Cryptography.HMACMD5(key, hashSize); - } -#endif // FEATURE_HMAC_MD5 -#if FEATURE_HMAC_SHA1 public static System.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key) { return new System.Security.Cryptography.HMACSHA1(key); @@ -179,19 +97,7 @@ public static HMACSHA1 CreateHMACSHA1(byte[] key, int hashSize) { return new HMACSHA1(key, hashSize); } -#else - public static global::SshNet.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key) - { - return new global::SshNet.Security.Cryptography.HMACSHA1(key); - } - public static global::SshNet.Security.Cryptography.HMACSHA1 CreateHMACSHA1(byte[] key, int hashSize) - { - return new global::SshNet.Security.Cryptography.HMACSHA1(key, hashSize); - } -#endif // FEATURE_HMAC_SHA1 - -#if FEATURE_HMAC_SHA256 public static System.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key) { return new System.Security.Cryptography.HMACSHA256(key); @@ -201,19 +107,7 @@ public static HMACSHA256 CreateHMACSHA256(byte[] key, int hashSize) { return new HMACSHA256(key, hashSize); } -#else - public static global::SshNet.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key) - { - return new global::SshNet.Security.Cryptography.HMACSHA256(key); - } - public static global::SshNet.Security.Cryptography.HMACSHA256 CreateHMACSHA256(byte[] key, int hashSize) - { - return new global::SshNet.Security.Cryptography.HMACSHA256(key, hashSize); - } -#endif // FEATURE_HMAC_SHA256 - -#if FEATURE_HMAC_SHA384 public static System.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key) { return new System.Security.Cryptography.HMACSHA384(key); @@ -223,19 +117,7 @@ public static HMACSHA384 CreateHMACSHA384(byte[] key, int hashSize) { return new HMACSHA384(key, hashSize); } -#else - public static global::SshNet.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key) - { - return new global::SshNet.Security.Cryptography.HMACSHA384(key); - } - - public static global::SshNet.Security.Cryptography.HMACSHA384 CreateHMACSHA384(byte[] key, int hashSize) - { - return new global::SshNet.Security.Cryptography.HMACSHA384(key, hashSize); - } -#endif // FEATURE_HMAC_SHA384 -#if FEATURE_HMAC_SHA512 public static System.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key) { return new System.Security.Cryptography.HMACSHA512(key); @@ -245,17 +127,6 @@ public static HMACSHA512 CreateHMACSHA512(byte[] key, int hashSize) { return new HMACSHA512(key, hashSize); } -#else - public static global::SshNet.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key) - { - return new global::SshNet.Security.Cryptography.HMACSHA512(key); - } - - public static global::SshNet.Security.Cryptography.HMACSHA512 CreateHMACSHA512(byte[] key, int hashSize) - { - return new global::SshNet.Security.Cryptography.HMACSHA512(key, hashSize); - } -#endif // FEATURE_HMAC_SHA512 #if FEATURE_HMAC_RIPEMD160 public static System.Security.Cryptography.HMACRIPEMD160 CreateHMACRIPEMD160(byte[] key) diff --git a/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs b/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs index 6fc1308ee..16ee1c0ab 100644 --- a/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs @@ -1,14 +1,10 @@ using System.Diagnostics; -#if FEATURE_DIAGNOSTICS_TRACESOURCE using System.Threading; -#endif // FEATURE_DIAGNOSTICS_TRACESOURCE namespace Renci.SshNet.Abstractions { internal static class DiagnosticAbstraction { -#if FEATURE_DIAGNOSTICS_TRACESOURCE - private static readonly SourceSwitch SourceSwitch = new SourceSwitch("SshNetSwitch"); public static bool IsEnabled(TraceEventType traceEventType) @@ -22,14 +18,11 @@ public static bool IsEnabled(TraceEventType traceEventType) #else new TraceSource("SshNet.Logging"); #endif // DEBUG -#endif // FEATURE_DIAGNOSTICS_TRACESOURCE [Conditional("DEBUG")] public static void Log(string text) { -#if FEATURE_DIAGNOSTICS_TRACESOURCE Loggging.TraceEvent(TraceEventType.Verbose, Thread.CurrentThread.ManagedThreadId, text); -#endif // FEATURE_DIAGNOSTICS_TRACESOURCE } } } diff --git a/src/Renci.SshNet/Abstractions/DnsAbstraction.cs b/src/Renci.SshNet/Abstractions/DnsAbstraction.cs index a2ac9d58f..707521eae 100644 --- a/src/Renci.SshNet/Abstractions/DnsAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/DnsAbstraction.cs @@ -1,10 +1,7 @@ using System; using System.Net; using System.Net.Sockets; - -#if FEATURE_TAP using System.Threading.Tasks; -#endif #if FEATURE_DNS_SYNC #elif FEATURE_DNS_APM @@ -92,7 +89,6 @@ public static IPAddress[] GetHostAddresses(string hostNameOrAddress) #endif } -#if FEATURE_TAP /// /// Returns the Internet Protocol (IP) addresses for the specified host. /// @@ -107,7 +103,5 @@ public static Task GetHostAddressesAsync(string hostNameOrAddress) { return Dns.GetHostAddressesAsync(hostNameOrAddress); } -#endif - } } diff --git a/src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs b/src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs index 0c7abf5c6..1140c9a60 100644 --- a/src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/ReflectionAbstraction.cs @@ -1,10 +1,6 @@ using System; using System.Collections.Generic; -#if FEATURE_REFLECTION_TYPEINFO -using System.Reflection; -#else using System.Linq; -#endif // FEATURE_REFLECTION_TYPEINFO namespace Renci.SshNet.Abstractions { @@ -13,12 +9,8 @@ internal static class ReflectionAbstraction public static IEnumerable GetCustomAttributes(this Type type, bool inherit) where T:Attribute { -#if FEATURE_REFLECTION_TYPEINFO - return type.GetTypeInfo().GetCustomAttributes(inherit); -#else var attributes = type.GetCustomAttributes(typeof(T), inherit); return attributes.Cast(); -#endif } } } diff --git a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs index e358767a1..e7740d574 100644 --- a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs @@ -3,9 +3,8 @@ using System.Net; using System.Net.Sockets; using System.Threading; -#if FEATURE_TAP using System.Threading.Tasks; -#endif + using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; @@ -17,11 +16,7 @@ public static bool CanRead(Socket socket) { if (socket.Connected) { -#if FEATURE_SOCKET_POLL return socket.Poll(-1, SelectMode.SelectRead) && socket.Available > 0; -#else - return true; -#endif // FEATURE_SOCKET_POLL } return false; @@ -40,11 +35,7 @@ public static bool CanWrite(Socket socket) { if (socket != null && socket.Connected) { -#if FEATURE_SOCKET_POLL return socket.Poll(-1, SelectMode.SelectWrite); -#else - return true; -#endif // FEATURE_SOCKET_POLL } return false; @@ -62,12 +53,10 @@ public static void Connect(Socket socket, IPEndPoint remoteEndpoint, TimeSpan co ConnectCore(socket, remoteEndpoint, connectTimeout, false); } -#if FEATURE_TAP public static async Task ConnectAsync(Socket socket, IPEndPoint remoteEndpoint, CancellationToken cancellationToken) { await socket.ConnectAsync(remoteEndpoint, cancellationToken).ConfigureAwait(false); } -#endif private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSpan connectTimeout, bool ownsSocket) { @@ -153,7 +142,6 @@ public static void ClearReadBuffer(Socket socket) public static int ReadPartial(Socket socket, byte[] buffer, int offset, int size, TimeSpan timeout) { -#if FEATURE_SOCKET_SYNC socket.ReceiveTimeout = (int) timeout.TotalMilliseconds; try @@ -167,53 +155,10 @@ public static int ReadPartial(Socket socket, byte[] buffer, int offset, int size "Socket read operation has timed out after {0:F0} milliseconds.", timeout.TotalMilliseconds)); throw; } -#elif FEATURE_SOCKET_EAP - var receiveCompleted = new ManualResetEvent(false); - var sendReceiveToken = new PartialSendReceiveToken(socket, receiveCompleted); - var args = new SocketAsyncEventArgs - { - RemoteEndPoint = socket.RemoteEndPoint, - UserToken = sendReceiveToken - }; - args.Completed += ReceiveCompleted; - args.SetBuffer(buffer, offset, size); - - try - { - if (socket.ReceiveAsync(args)) - { - if (!receiveCompleted.WaitOne(timeout)) - throw new SshOperationTimeoutException( - string.Format( - CultureInfo.InvariantCulture, - "Socket read operation has timed out after {0:F0} milliseconds.", - timeout.TotalMilliseconds)); - } - else - { - sendReceiveToken.Process(args); - } - - if (args.SocketError != SocketError.Success) - throw new SocketException((int) args.SocketError); - - return args.BytesTransferred; - } - finally - { - // initialize token to avoid the waithandle getting used after it's disposed - args.UserToken = null; - args.Dispose(); - receiveCompleted.Dispose(); - } -#else - #error Receiving data from a Socket is not implemented. -#endif } public static void ReadContinuous(Socket socket, byte[] buffer, int offset, int size, Action processReceivedBytesAction) { -#if FEATURE_SOCKET_SYNC // do not time-out receive socket.ReceiveTimeout = 0; @@ -247,30 +192,6 @@ public static void ReadContinuous(Socket socket, byte[] buffer, int offset, int } } } -#elif FEATURE_SOCKET_EAP - var completionWaitHandle = new ManualResetEvent(false); - var readToken = new ContinuousReceiveToken(socket, processReceivedBytesAction, completionWaitHandle); - var args = new SocketAsyncEventArgs - { - RemoteEndPoint = socket.RemoteEndPoint, - UserToken = readToken - }; - args.Completed += ReceiveCompleted; - args.SetBuffer(buffer, offset, size); - - if (!socket.ReceiveAsync(args)) - { - ReceiveCompleted(null, args); - } - - completionWaitHandle.WaitOne(); - completionWaitHandle.Dispose(); - - if (readToken.Exception != null) - throw readToken.Exception; -#else - #error Receiving data from a Socket is not implemented. -#endif } /// @@ -327,12 +248,10 @@ public static byte[] Read(Socket socket, int size, TimeSpan timeout) return buffer; } -#if FEATURE_TAP public static Task ReadAsync(Socket socket, byte[] buffer, int offset, int length, CancellationToken cancellationToken) { return socket.ReceiveAsync(buffer, offset, length, cancellationToken); } -#endif /// /// Receives data from a bound into a receive buffer. @@ -358,7 +277,6 @@ public static Task ReadAsync(Socket socket, byte[] buffer, int offset, int /// public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeSpan readTimeout) { -#if FEATURE_SOCKET_SYNC var totalBytesRead = 0; var totalBytesToRead = size; @@ -386,52 +304,12 @@ public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeS throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture, "Socket read operation has timed out after {0:F0} milliseconds.", readTimeout.TotalMilliseconds)); - throw; + throw; } } while (totalBytesRead < totalBytesToRead); return totalBytesRead; -#elif FEATURE_SOCKET_EAP - var receiveCompleted = new ManualResetEvent(false); - var sendReceiveToken = new BlockingSendReceiveToken(socket, buffer, offset, size, receiveCompleted); - - var args = new SocketAsyncEventArgs - { - UserToken = sendReceiveToken, - RemoteEndPoint = socket.RemoteEndPoint - }; - args.Completed += ReceiveCompleted; - args.SetBuffer(buffer, offset, size); - - try - { - if (socket.ReceiveAsync(args)) - { - if (!receiveCompleted.WaitOne(readTimeout)) - throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture, - "Socket read operation has timed out after {0:F0} milliseconds.", readTimeout.TotalMilliseconds)); - } - else - { - sendReceiveToken.Process(args); - } - - if (args.SocketError != SocketError.Success) - throw new SocketException((int) args.SocketError); - - return sendReceiveToken.TotalBytesTransferred; - } - finally - { - // initialize token to avoid the waithandle getting used after it's disposed - args.UserToken = null; - args.Dispose(); - receiveCompleted.Dispose(); - } -#else -#error Receiving data from a Socket is not implemented. -#endif } public static void Send(Socket socket, byte[] data) @@ -441,7 +319,6 @@ public static void Send(Socket socket, byte[] data) public static void Send(Socket socket, byte[] data, int offset, int size) { -#if FEATURE_SOCKET_SYNC var totalBytesSent = 0; // how many bytes are already sent var totalBytesToSend = size; @@ -467,46 +344,6 @@ public static void Send(Socket socket, byte[] data, int offset, int size) throw; // any serious error occurr } } while (totalBytesSent < totalBytesToSend); -#elif FEATURE_SOCKET_EAP - var sendCompleted = new ManualResetEvent(false); - var sendReceiveToken = new BlockingSendReceiveToken(socket, data, offset, size, sendCompleted); - var socketAsyncSendArgs = new SocketAsyncEventArgs - { - RemoteEndPoint = socket.RemoteEndPoint, - UserToken = sendReceiveToken - }; - socketAsyncSendArgs.SetBuffer(data, offset, size); - socketAsyncSendArgs.Completed += SendCompleted; - - try - { - if (socket.SendAsync(socketAsyncSendArgs)) - { - if (!sendCompleted.WaitOne()) - throw new SocketException((int) SocketError.TimedOut); - } - else - { - sendReceiveToken.Process(socketAsyncSendArgs); - } - - if (socketAsyncSendArgs.SocketError != SocketError.Success) - throw new SocketException((int) socketAsyncSendArgs.SocketError); - - if (sendReceiveToken.TotalBytesTransferred == 0) - throw new SshConnectionException("An established connection was aborted by the server.", - DisconnectReason.ConnectionLost); - } - finally - { - // initialize token to avoid the completion waithandle getting used after it's disposed - socketAsyncSendArgs.UserToken = null; - socketAsyncSendArgs.Dispose(); - sendCompleted.Dispose(); - } -#else - #error Sending data to a Socket is not implemented. -#endif } public static bool IsErrorResumable(SocketError socketError) @@ -531,199 +368,5 @@ private static void ConnectCompleted(object sender, SocketAsyncEventArgs e) } #endif // FEATURE_SOCKET_EAP -#if FEATURE_SOCKET_EAP && !FEATURE_SOCKET_SYNC - private static void ReceiveCompleted(object sender, SocketAsyncEventArgs e) - { - var sendReceiveToken = (Token) e.UserToken; - if (sendReceiveToken != null) - sendReceiveToken.Process(e); - } - - private static void SendCompleted(object sender, SocketAsyncEventArgs e) - { - var sendReceiveToken = (Token) e.UserToken; - if (sendReceiveToken != null) - sendReceiveToken.Process(e); - } - - private interface Token - { - void Process(SocketAsyncEventArgs args); - } - - private class BlockingSendReceiveToken : Token - { - public BlockingSendReceiveToken(Socket socket, byte[] buffer, int offset, int size, EventWaitHandle completionWaitHandle) - { - _socket = socket; - _buffer = buffer; - _offset = offset; - _bytesToTransfer = size; - _completionWaitHandle = completionWaitHandle; - } - - public void Process(SocketAsyncEventArgs args) - { - if (args.SocketError == SocketError.Success) - { - TotalBytesTransferred += args.BytesTransferred; - - if (TotalBytesTransferred == _bytesToTransfer) - { - // finished transferring specified bytes - _completionWaitHandle.Set(); - return; - } - - if (args.BytesTransferred == 0) - { - // remote server closed the connection - _completionWaitHandle.Set(); - return; - } - - _offset += args.BytesTransferred; - args.SetBuffer(_buffer, _offset, _bytesToTransfer - TotalBytesTransferred); - ResumeOperation(args); - return; - } - - if (IsErrorResumable(args.SocketError)) - { - ThreadAbstraction.Sleep(30); - ResumeOperation(args); - return; - } - - // we're dealing with a (fatal) error - _completionWaitHandle.Set(); - } - - private void ResumeOperation(SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.Receive: - _socket.ReceiveAsync(args); - break; - case SocketAsyncOperation.Send: - _socket.SendAsync(args); - break; - } - } - - private readonly int _bytesToTransfer; - public int TotalBytesTransferred { get; private set; } - private readonly EventWaitHandle _completionWaitHandle; - private readonly Socket _socket; - private readonly byte[] _buffer; - private int _offset; - } - - private class PartialSendReceiveToken : Token - { - public PartialSendReceiveToken(Socket socket, EventWaitHandle completionWaitHandle) - { - _socket = socket; - _completionWaitHandle = completionWaitHandle; - } - - public void Process(SocketAsyncEventArgs args) - { - if (args.SocketError == SocketError.Success) - { - _completionWaitHandle.Set(); - return; - } - - if (IsErrorResumable(args.SocketError)) - { - ThreadAbstraction.Sleep(30); - ResumeOperation(args); - return; - } - - // we're dealing with a (fatal) error - _completionWaitHandle.Set(); - } - - private void ResumeOperation(SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.Receive: - _socket.ReceiveAsync(args); - break; - case SocketAsyncOperation.Send: - _socket.SendAsync(args); - break; - } - } - - private readonly EventWaitHandle _completionWaitHandle; - private readonly Socket _socket; - } - - private class ContinuousReceiveToken : Token - { - public ContinuousReceiveToken(Socket socket, Action processReceivedBytesAction, EventWaitHandle completionWaitHandle) - { - _socket = socket; - _processReceivedBytesAction = processReceivedBytesAction; - _completionWaitHandle = completionWaitHandle; - } - - public Exception Exception { get; private set; } - - public void Process(SocketAsyncEventArgs args) - { - if (args.SocketError == SocketError.Success) - { - if (args.BytesTransferred == 0) - { - // remote socket was closed - _completionWaitHandle.Set(); - return; - } - - _processReceivedBytesAction(args.Buffer, args.Offset, args.BytesTransferred); - ResumeOperation(args); - return; - } - - if (IsErrorResumable(args.SocketError)) - { - ThreadAbstraction.Sleep(30); - ResumeOperation(args); - return; - } - - if (args.SocketError != SocketError.OperationAborted) - { - Exception = new SocketException((int) args.SocketError); - } - - // we're dealing with a (fatal) error - _completionWaitHandle.Set(); - } - - private void ResumeOperation(SocketAsyncEventArgs args) - { - switch (args.LastOperation) - { - case SocketAsyncOperation.Receive: - _socket.ReceiveAsync(args); - break; - case SocketAsyncOperation.Send: - _socket.SendAsync(args); - break; - } - } - - private readonly EventWaitHandle _completionWaitHandle; - private readonly Socket _socket; - private readonly Action _processReceivedBytesAction; - } -#endif // FEATURE_SOCKET_EAP && !FEATURE_SOCKET_SYNC } } diff --git a/src/Renci.SshNet/Abstractions/SocketExtensions.cs b/src/Renci.SshNet/Abstractions/SocketExtensions.cs index d763e1a34..7d3c30f93 100644 --- a/src/Renci.SshNet/Abstractions/SocketExtensions.cs +++ b/src/Renci.SshNet/Abstractions/SocketExtensions.cs @@ -1,5 +1,4 @@ -#if FEATURE_TAP -using System; +using System; using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; @@ -116,4 +115,3 @@ public static async Task ReceiveAsync(this Socket socket, byte[] buffer, in } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs b/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs index 8c344404b..35824ee10 100644 --- a/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/ThreadAbstraction.cs @@ -10,13 +10,7 @@ internal static class ThreadAbstraction /// The number of milliseconds for which the thread is suspended. public static void Sleep(int millisecondsTimeout) { -#if FEATURE_THREAD_SLEEP System.Threading.Thread.Sleep(millisecondsTimeout); -#elif FEATURE_THREAD_TAP - System.Threading.Tasks.Task.Delay(millisecondsTimeout).GetAwaiter().GetResult(); -#else - #error Suspend of the current thread is not implemented. -#endif } public static void ExecuteThreadLongRunning(Action action) @@ -24,15 +18,8 @@ public static void ExecuteThreadLongRunning(Action action) if (action == null) throw new ArgumentNullException("action"); -#if FEATURE_THREAD_TAP var taskCreationOptions = System.Threading.Tasks.TaskCreationOptions.LongRunning; System.Threading.Tasks.Task.Factory.StartNew(action, taskCreationOptions); -#else - new System.Threading.Thread(() => action()) - { - IsBackground = true - }.Start(); -#endif } /// @@ -41,16 +28,10 @@ public static void ExecuteThreadLongRunning(Action action) /// The action to execute. public static void ExecuteThread(Action action) { -#if FEATURE_THREAD_THREADPOOL if (action == null) throw new ArgumentNullException("action"); System.Threading.ThreadPool.QueueUserWorkItem(o => action()); -#elif FEATURE_THREAD_TAP - System.Threading.Tasks.Task.Run(action); -#else - #error Execution of action in a separate thread is not implemented. -#endif } } } diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index 754396108..fdc4e3a39 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -1,9 +1,8 @@ using System; using System.Net.Sockets; using System.Threading; -#if FEATURE_TAP using System.Threading.Tasks; -#endif + using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; @@ -242,7 +241,6 @@ public void Connect() StartKeepAliveTimer(); } -#if FEATURE_TAP /// /// Asynchronously connects client to the server. /// @@ -297,7 +295,6 @@ public async Task ConnectAsync(CancellationToken cancellationToken) } StartKeepAliveTimer(); } -#endif /// /// Disconnects client from the server. @@ -533,7 +530,6 @@ private ISession CreateAndConnectSession() } } -#if FEATURE_TAP private async Task CreateAndConnectSessionAsync(CancellationToken cancellationToken) { var session = _serviceFactory.CreateSession(ConnectionInfo, _serviceFactory.CreateSocketFactory()); @@ -551,7 +547,6 @@ private async Task CreateAndConnectSessionAsync(CancellationToken canc throw; } } -#endif private void DisposeSession(ISession session) { diff --git a/src/Renci.SshNet/Common/ASCIIEncoding.cs b/src/Renci.SshNet/Common/ASCIIEncoding.cs deleted file mode 100644 index f41c49de8..000000000 --- a/src/Renci.SshNet/Common/ASCIIEncoding.cs +++ /dev/null @@ -1,167 +0,0 @@ -#if !FEATURE_ENCODING_ASCII - -using System; -using System.Text; - -namespace Renci.SshNet.Common -{ - /// - /// Implementation of ASCII Encoding - /// - public class ASCIIEncoding : Encoding - { - private readonly char _fallbackChar; - - private static readonly char[] ByteToChar; - - static ASCIIEncoding() - { - if (ByteToChar == null) - { - ByteToChar = new char[128]; - var ch = '\0'; - for (byte i = 0; i < 128; i++) - { - ByteToChar[i] = ch++; - } - } - } - - /// - /// Initializes a new instance of the class. - /// - public ASCIIEncoding() - { - _fallbackChar = '?'; - } - - /// - /// Calculates the number of bytes produced by encoding a set of characters from the specified character array. - /// - /// The character array containing the set of characters to encode. - /// The index of the first character to encode. - /// The number of characters to encode. - /// - /// The number of bytes produced by encoding the specified characters. - /// - /// is null. - /// or is less than zero.-or- and do not denote a valid range in . - public override int GetByteCount(char[] chars, int index, int count) - { - return count; - } - - /// - /// Encodes a set of characters from the specified character array into the specified byte array. - /// - /// The character array containing the set of characters to encode. - /// The index of the first character to encode. - /// The number of characters to encode. - /// The byte array to contain the resulting sequence of bytes. - /// The index at which to start writing the resulting sequence of bytes. - /// - /// The actual number of bytes written into . - /// - /// is null.-or- is null. - /// or or is less than zero.-or- and do not denote a valid range in .-or- is not a valid index in . - /// does not have enough capacity from to the end of the array to accommodate the resulting bytes. - public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) - { - for (var i = 0; i < charCount && i < chars.Length; i++) - { - var b = (byte)chars[i + charIndex]; - - if (b > 127) - b = (byte) _fallbackChar; - - bytes[i + byteIndex] = b; - } - return charCount; - } - - /// - /// Calculates the number of characters produced by decoding a sequence of bytes from the specified byte array. - /// - /// The byte array containing the sequence of bytes to decode. - /// The index of the first byte to decode. - /// The number of bytes to decode. - /// - /// The number of characters produced by decoding the specified sequence of bytes. - /// - /// is null. - /// or is less than zero.-or- and do not denote a valid range in . - public override int GetCharCount(byte[] bytes, int index, int count) - { - return count; - } - - /// - /// Decodes a sequence of bytes from the specified byte array into the specified character array. - /// - /// The byte array containing the sequence of bytes to decode. - /// The index of the first byte to decode. - /// The number of bytes to decode. - /// The character array to contain the resulting set of characters. - /// The index at which to start writing the resulting set of characters. - /// - /// The actual number of characters written into . - /// - /// is null.-or- is null. - /// or or is less than zero.-or- and do not denote a valid range in .-or- is not a valid index in . - /// does not have enough capacity from to the end of the array to accommodate the resulting characters. - public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) - { - for (var i = 0; i < byteCount; i++) - { - var b = bytes[i + byteIndex]; - char ch; - - if (b > 127) - { - ch = _fallbackChar; - } - else - { - ch = ByteToChar[b]; - } - - chars[i + charIndex] = ch; - } - return byteCount; - } - - /// - /// Calculates the maximum number of bytes produced by encoding the specified number of characters. - /// - /// The number of characters to encode. - /// - /// The maximum number of bytes produced by encoding the specified number of characters. - /// - /// is less than zero. - public override int GetMaxByteCount(int charCount) - { - if (charCount < 0) - throw new ArgumentOutOfRangeException("charCount", "Non-negative number required."); - - return charCount + 1; - } - - /// - /// Calculates the maximum number of characters produced by decoding the specified number of bytes. - /// - /// The number of bytes to decode. - /// - /// The maximum number of characters produced by decoding the specified number of bytes. - /// - /// is less than zero. - public override int GetMaxCharCount(int byteCount) - { - if (byteCount < 0) - throw new ArgumentOutOfRangeException("byteCount", "Non-negative number required."); - - return byteCount; - } - } -} - -#endif // !FEATURE_ENCODING_ASCII \ No newline at end of file diff --git a/src/Renci.SshNet/Common/CountdownEvent.cs b/src/Renci.SshNet/Common/CountdownEvent.cs deleted file mode 100644 index 7387a786f..000000000 --- a/src/Renci.SshNet/Common/CountdownEvent.cs +++ /dev/null @@ -1,171 +0,0 @@ -#if !FEATURE_THREAD_COUNTDOWNEVENT - -using System; -using System.Threading; - -namespace Renci.SshNet.Common -{ - /// - /// Represents a synchronization primitive that is signaled when its count reaches zero. - /// - internal class CountdownEvent : IDisposable - { - private int _count; - private ManualResetEvent _event; - private bool _disposed; - - /// - /// Initializes a new instance of class with the specified count. - /// - /// The number of signals initially required to set the . - /// is less than zero. - /// - /// If is zero, the event is created in a signaled state. - /// - public CountdownEvent(int initialCount) - { - if (initialCount < 0) - { - throw new ArgumentOutOfRangeException("initialCount"); - } - - _count = initialCount; - - var initialState = _count == 0; - _event = new ManualResetEvent(initialState); - } - - /// - /// Gets the number of remaining signals required to set the event. - /// - /// - /// The number of remaining signals required to set the event. - /// - public int CurrentCount - { - get { return _count; } - } - - /// - /// Indicates whether the 's current count has reached zero. - /// - /// - /// true if the current count is zero; otherwise, false. - /// - public bool IsSet - { - get { return _count == 0; } - } - - /// - /// Gets a that is used to wait for the event to be set. - /// - /// - /// A that is used to wait for the event to be set. - /// - /// The current instance has already been disposed. - public WaitHandle WaitHandle - { - get - { - EnsureNotDisposed(); - - return _event; - } - } - - - /// - /// Registers a signal with the , decrementing the value of . - /// - /// - /// true if the signal caused the count to reach zero and the event was set; otherwise, false. - /// - /// The current instance has already been disposed. - /// The current instance is already set. - public bool Signal() - { - EnsureNotDisposed(); - - if (_count <= 0) - throw new InvalidOperationException("Invalid attempt made to decrement the event's count below zero."); - - var newCount = Interlocked.Decrement(ref _count); - if (newCount == 0) - { - _event.Set(); - return true; - } - - return false; - } - - /// - /// Increments the 's current count by one. - /// - /// The current instance has already been disposed. - /// The current instance is already set. - /// is equal to or greather than . - public void AddCount() - { - EnsureNotDisposed(); - - if (_count == int.MaxValue) - throw new InvalidOperationException("TODO"); - - Interlocked.Increment(ref _count); - } - - /// - /// Blocks the current thread until the is set, using a - /// to measure the timeout. - /// - /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. - /// - /// true if the was set; otherwise, false. - /// - /// The current instance has already been disposed. - public bool Wait(TimeSpan timeout) - { - EnsureNotDisposed(); - - return _event.WaitOne(timeout); - } - - /// - /// Releases all resources used by the current instance of the class. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases the unmanaged resources used by the , and optionally releases the managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - var theEvent = _event; - if (theEvent != null) - { - _event = null; - theEvent.Dispose(); - } - - _disposed = true; - } - } - - private void EnsureNotDisposed() - { - if (_disposed) - throw new ObjectDisposedException(GetType().Name); - } - } -} - -#endif // FEATURE_THREAD_COUNTDOWNEVENT \ No newline at end of file diff --git a/src/Renci.SshNet/Common/Extensions.cs b/src/Renci.SshNet/Common/Extensions.cs index 17d72d7fb..3a5311f07 100644 --- a/src/Renci.SshNet/Common/Extensions.cs +++ b/src/Renci.SshNet/Common/Extensions.cs @@ -5,9 +5,6 @@ using System.Net; using System.Net.Sockets; using System.Text; -#if !FEATURE_WAITHANDLE_DISPOSE -using System.Threading; -#endif // !FEATURE_WAITHANDLE_DISPOSE using Renci.SshNet.Abstractions; using Renci.SshNet.Messages; @@ -305,62 +302,5 @@ internal static bool IsConnected(this Socket socket) return false; return socket.Connected; } - -#if !FEATURE_SOCKET_DISPOSE - /// - /// Disposes the specified socket. - /// - /// The socket. - [DebuggerNonUserCode] - internal static void Dispose(this Socket socket) - { - if (socket == null) - throw new NullReferenceException(); - - socket.Close(); - } -#endif // !FEATURE_SOCKET_DISPOSE - -#if !FEATURE_WAITHANDLE_DISPOSE - /// - /// Disposes the specified handle. - /// - /// The handle. - [DebuggerNonUserCode] - internal static void Dispose(this WaitHandle handle) - { - if (handle == null) - throw new NullReferenceException(); - - handle.Close(); - } -#endif // !FEATURE_WAITHANDLE_DISPOSE - -#if !FEATURE_HASHALGORITHM_DISPOSE - /// - /// Disposes the specified algorithm. - /// - /// The algorithm. - [DebuggerNonUserCode] - internal static void Dispose(this System.Security.Cryptography.HashAlgorithm algorithm) - { - if (algorithm == null) - throw new NullReferenceException(); - - algorithm.Clear(); - } -#endif // FEATURE_HASHALGORITHM_DISPOSE - -#if !FEATURE_STRINGBUILDER_CLEAR - /// - /// Clears the contents of the string builder. - /// - /// The to clear. - public static void Clear(this StringBuilder value) - { - value.Length = 0; - value.Capacity = 16; - } -#endif // !FEATURE_STRINGBUILDER_CLEAR } } diff --git a/src/Renci.SshNet/Common/PacketDump.cs b/src/Renci.SshNet/Common/PacketDump.cs index 7b50582cb..cd68549d6 100644 --- a/src/Renci.SshNet/Common/PacketDump.cs +++ b/src/Renci.SshNet/Common/PacketDump.cs @@ -79,13 +79,9 @@ private static string AsHex(byte[] data, int length) private static string AsAscii(byte[] data, int length) { -#if FEATURE_ENCODING_ASCII - var encoding = Encoding.ASCII; -#else - var encoding = new ASCIIEncoding(); -#endif + var encoding = Encoding.ASCII; - var ascii = new StringBuilder(); + var ascii = new StringBuilder(); const char dot = '.'; for (var i = 0; i < length; i++) diff --git a/src/Renci.SshNet/Common/SshData.cs b/src/Renci.SshNet/Common/SshData.cs index 8e4eca406..844bace7a 100644 --- a/src/Renci.SshNet/Common/SshData.cs +++ b/src/Renci.SshNet/Common/SshData.cs @@ -11,11 +11,8 @@ public abstract class SshData { internal const int DefaultCapacity = 64; -#if FEATURE_ENCODING_ASCII internal static readonly Encoding Ascii = Encoding.ASCII; -#else - internal static readonly Encoding Ascii = new ASCIIEncoding(); -#endif + internal static readonly Encoding Utf8 = Encoding.UTF8; private SshDataStream _stream; diff --git a/src/Renci.SshNet/Common/SshDataStream.cs b/src/Renci.SshNet/Common/SshDataStream.cs index 010800c3e..0e024491c 100644 --- a/src/Renci.SshNet/Common/SshDataStream.cs +++ b/src/Renci.SshNet/Common/SshDataStream.cs @@ -252,13 +252,7 @@ public override byte[] ToArray() { if (Capacity == Length) { -#if FEATURE_MEMORYSTREAM_GETBUFFER return GetBuffer(); -#elif FEATURE_MEMORYSTREAM_TRYGETBUFFER - ArraySegment buffer; - if (TryGetBuffer(out buffer)) - return buffer.Array; -#endif } return base.ToArray(); } diff --git a/src/Renci.SshNet/Connection/ConnectorBase.cs b/src/Renci.SshNet/Connection/ConnectorBase.cs index ffa026750..6bcd556fd 100644 --- a/src/Renci.SshNet/Connection/ConnectorBase.cs +++ b/src/Renci.SshNet/Connection/ConnectorBase.cs @@ -5,10 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; - -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet.Connection { @@ -26,9 +23,7 @@ protected ConnectorBase(ISocketFactory socketFactory) public abstract Socket Connect(IConnectionInfo connectionInfo); -#if FEATURE_TAP public abstract Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken); -#endif /// /// Establishes a socket connection to the specified host and port. @@ -63,7 +58,6 @@ protected Socket SocketConnect(string host, int port, TimeSpan timeout) } } -#if FEATURE_TAP /// /// Establishes a socket connection to the specified host and port. /// @@ -97,7 +91,6 @@ protected async Task SocketConnectAsync(string host, int port, Cancellat throw; } } -#endif protected static byte SocketReadByte(Socket socket) { diff --git a/src/Renci.SshNet/Connection/DirectConnector.cs b/src/Renci.SshNet/Connection/DirectConnector.cs index 0d07bb936..0f428fc31 100644 --- a/src/Renci.SshNet/Connection/DirectConnector.cs +++ b/src/Renci.SshNet/Connection/DirectConnector.cs @@ -14,11 +14,9 @@ public override Socket Connect(IConnectionInfo connectionInfo) return SocketConnect(connectionInfo.Host, connectionInfo.Port, connectionInfo.Timeout); } -#if FEATURE_TAP public override System.Threading.Tasks.Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken) { return SocketConnectAsync(connectionInfo.Host, connectionInfo.Port, cancellationToken); } -#endif } } diff --git a/src/Renci.SshNet/Connection/IConnector.cs b/src/Renci.SshNet/Connection/IConnector.cs index 9eccabe62..e49587b74 100644 --- a/src/Renci.SshNet/Connection/IConnector.cs +++ b/src/Renci.SshNet/Connection/IConnector.cs @@ -7,8 +7,6 @@ internal interface IConnector { Socket Connect(IConnectionInfo connectionInfo); -#if FEATURE_TAP System.Threading.Tasks.Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken); -#endif } } diff --git a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs index c804c291f..252cda986 100644 --- a/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs +++ b/src/Renci.SshNet/Connection/IProtocolVersionExchange.cs @@ -19,8 +19,6 @@ internal interface IProtocolVersionExchange /// SshIdentification Start(string clientVersion, Socket socket, TimeSpan timeout); -#if FEATURE_TAP System.Threading.Tasks.Task StartAsync(string clientVersion, Socket socket, System.Threading.CancellationToken cancellationToken); -#endif } } diff --git a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs index 4e6957c10..716b8a42c 100644 --- a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs +++ b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs @@ -8,9 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet.Connection { @@ -24,11 +22,7 @@ internal class ProtocolVersionExchange : IProtocolVersionExchange { private const byte Null = 0x00; -#if FEATURE_REGEX_COMPILE private static readonly Regex ServerVersionRe = new Regex("^SSH-(?[^-]+)-(?.+?)([ ](?.+))?$", RegexOptions.Compiled); -#else - private static readonly Regex ServerVersionRe = new Regex("^SSH-(?[^-]+)-(?.+?)([ ](?.+))?$"); -#endif /// /// Performs the SSH protocol version exchange. @@ -82,7 +76,6 @@ public SshIdentification Start(string clientVersion, Socket socket, TimeSpan tim } } -#if FEATURE_TAP public async Task StartAsync(string clientVersion, Socket socket, CancellationToken cancellationToken) { // Immediately send the identification string since the spec states both sides MUST send an identification string @@ -125,7 +118,6 @@ public async Task StartAsync(string clientVersion, Socket soc } } } -#endif private static string GetGroupValue(Match match, string groupName) { @@ -203,7 +195,6 @@ private static string SocketReadLine(Socket socket, TimeSpan timeout, List return null; } -#if FEATURE_TAP private static async Task SocketReadLineAsync(Socket socket, CancellationToken cancellationToken, List buffer) { var data = new byte[1]; @@ -254,7 +245,5 @@ private static async Task SocketReadLineAsync(Socket socket, Cancellatio } } } -#endif - } } diff --git a/src/Renci.SshNet/Connection/ProxyConnector.cs b/src/Renci.SshNet/Connection/ProxyConnector.cs index 6cc2ac9d4..164ae4835 100644 --- a/src/Renci.SshNet/Connection/ProxyConnector.cs +++ b/src/Renci.SshNet/Connection/ProxyConnector.cs @@ -1,12 +1,8 @@ -#if !FEATURE_SOCKET_DISPOSE -using Renci.SshNet.Common; -#endif -using System; +using System; using System.Net.Sockets; -#if FEATURE_TAP using System.Threading; using System.Threading.Tasks; -#endif + namespace Renci.SshNet.Connection { @@ -19,7 +15,6 @@ public ProxyConnector(ISocketFactory socketFactory) : protected abstract void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket); -#if FEATURE_TAP // ToDo: Performs async/sync fallback, true async version should be implemented in derived classes protected virtual Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, Socket socket, CancellationToken cancellationToken) { @@ -31,7 +26,6 @@ protected virtual Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, S } return Task.CompletedTask; } -#endif public override Socket Connect(IConnectionInfo connectionInfo) { @@ -51,7 +45,6 @@ public override Socket Connect(IConnectionInfo connectionInfo) } } -#if FEATURE_TAP public override async Task ConnectAsync(IConnectionInfo connectionInfo, CancellationToken cancellationToken) { var socket = await SocketConnectAsync(connectionInfo.ProxyHost, connectionInfo.ProxyPort, cancellationToken).ConfigureAwait(false); @@ -69,6 +62,5 @@ public override async Task ConnectAsync(IConnectionInfo connectionInfo, throw; } } -#endif } } diff --git a/src/Renci.SshNet/Connection/Socks4Connector.cs b/src/Renci.SshNet/Connection/Socks4Connector.cs index ccf4e1456..d507872c6 100644 --- a/src/Renci.SshNet/Connection/Socks4Connector.cs +++ b/src/Renci.SshNet/Connection/Socks4Connector.cs @@ -125,11 +125,7 @@ private static byte[] GetProxyUserBytes(string proxyUser) return Array.Empty; } -#if FEATURE_ENCODING_ASCII return Encoding.ASCII.GetBytes(proxyUser); -#else - return new ASCIIEncoding().GetBytes(proxyUser); -#endif } } } diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs index af8e1ca5c..f0f8b57c7 100644 --- a/src/Renci.SshNet/ConnectionInfo.cs +++ b/src/Renci.SshNet/ConnectionInfo.cs @@ -382,11 +382,9 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy HostKeyAlgorithms = new Dictionary> { {"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)}, -#if FEATURE_ECDSA {"ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data)}, {"ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data)}, {"ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data)}, -#endif {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)}, {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)}, //{"x509v3-sign-rsa", () => { ... }, diff --git a/src/Renci.SshNet/IBaseClient.cs b/src/Renci.SshNet/IBaseClient.cs index bd9518ac4..c11adb4f6 100644 --- a/src/Renci.SshNet/IBaseClient.cs +++ b/src/Renci.SshNet/IBaseClient.cs @@ -2,9 +2,7 @@ using System; using System.Net.Sockets; using System.Threading; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet { @@ -68,7 +66,6 @@ public interface IBaseClient /// Failed to establish proxy connection. void Connect(); -#if FEATURE_TAP /// /// Asynchronously connects client to the server. /// @@ -82,7 +79,6 @@ public interface IBaseClient /// Authentication of SSH session failed. /// Failed to establish proxy connection. Task ConnectAsync(CancellationToken cancellationToken); -#endif /// /// Disconnects client from the server. diff --git a/src/Renci.SshNet/ISession.cs b/src/Renci.SshNet/ISession.cs index cde647a46..bc123c776 100644 --- a/src/Renci.SshNet/ISession.cs +++ b/src/Renci.SshNet/ISession.cs @@ -6,9 +6,7 @@ using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages.Connection; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet { @@ -57,7 +55,6 @@ internal interface ISession : IDisposable /// Failed to establish proxy connection. void Connect(); -#if FEATURE_TAP /// /// Asynchronously connects to the server. /// @@ -68,7 +65,6 @@ internal interface ISession : IDisposable /// Authentication of SSH session failed. /// Failed to establish proxy connection. Task ConnectAsync(CancellationToken cancellationToken); -#endif /// /// Create a new SSH session channel. diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index eda042eff..99e1e7b06 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -4,10 +4,8 @@ using System.Text; using Renci.SshNet.Sftp; using Renci.SshNet.Common; -#if FEATURE_TAP using System.Threading; using System.Threading.Tasks; -#endif namespace Renci.SshNet { @@ -492,7 +490,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// The method was called after the client was disposed. void DeleteFile(string path); -#if FEATURE_TAP /// /// Asynchronously deletes remote file specified by path. /// @@ -506,7 +503,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. Task DeleteFileAsync(string path, CancellationToken cancellationToken); -#endif /// /// Downloads remote file specified by the path into the stream. @@ -673,7 +669,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// The method was called after the client was disposed. SftpFileSytemInformation GetStatus(string path); -#if FEATURE_TAP /// /// Asynchronously gets status using statvfs@openssh.com request. /// @@ -687,7 +682,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// is null. /// The method was called after the client was disposed. Task GetStatusAsync(string path, CancellationToken cancellationToken); -#endif /// /// Retrieves list of files in remote directory. @@ -704,8 +698,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// The method was called after the client was disposed. IEnumerable ListDirectory(string path, Action listCallback = null); -#if FEATURE_TAP - /// /// Asynchronously retrieves list of files in remote directory. /// @@ -721,7 +713,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. Task> ListDirectoryAsync(string path, CancellationToken cancellationToken); -#endif /// /// Opens a on the specified path with read/write access. @@ -750,7 +741,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// The method was called after the client was disposed. SftpFileStream Open(string path, FileMode mode, FileAccess access); -#if FEATURE_TAP /// /// Asynchronously opens a on the specified path, with the specified mode and access. /// @@ -766,7 +756,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// Client is not connected. /// The method was called after the client was disposed. Task OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken); -#endif /// /// Opens an existing file for reading. @@ -906,7 +895,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// The method was called after the client was disposed. void RenameFile(string oldPath, string newPath); -#if FEATURE_TAP /// /// Asynchronously renames remote file from old path to new path. /// @@ -920,7 +908,6 @@ public interface ISftpClient : IBaseClient, IDisposable /// A SSH error where is the message from the remote host. /// The method was called after the client was disposed. Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken); -#endif /// /// Renames remote file from old path to new path. diff --git a/src/Renci.SshNet/NoneAuthenticationMethod.cs b/src/Renci.SshNet/NoneAuthenticationMethod.cs index a5d842fd7..93586ade9 100644 --- a/src/Renci.SshNet/NoneAuthenticationMethod.cs +++ b/src/Renci.SshNet/NoneAuthenticationMethod.cs @@ -1,8 +1,5 @@ using System; using System.Threading; -#if !FEATURE_WAITHANDLE_DISPOSE -using Renci.SshNet.Common; -#endif // !FEATURE_WAITHANDLE_DISPOSE using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages; diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index f29b3e958..5ec7f248d 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -66,11 +66,8 @@ namespace Renci.SshNet public class PrivateKeyFile : IPrivateKeySource, IDisposable { private static readonly Regex PrivateKeyRegex = new Regex(@"^-+ *BEGIN (?\w+( \w+)*) PRIVATE KEY *-+\r?\n((Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)|(Comment: ""?[^\r\n]*""?\r?\n))?(?([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k PRIVATE KEY *-+", -#if FEATURE_REGEX_COMPILE RegexOptions.Compiled | RegexOptions.Multiline); -#else - RegexOptions.Multiline); -#endif + private Key _key; @@ -221,12 +218,10 @@ private void Open(Stream privateKey, string passPhrase) _key = new DsaKey(decryptedData); HostKey = new KeyHostAlgorithm("ssh-dss", _key); break; -#if FEATURE_ECDSA case "EC": _key = new EcdsaKey(decryptedData); HostKey = new KeyHostAlgorithm(_key.ToString(), _key); break; -#endif case "OPENSSH": _key = ParseOpenSshV1Key(decryptedData, passPhrase); HostKey = new KeyHostAlgorithm(_key.ToString(), _key); @@ -497,7 +492,6 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) unencryptedPrivateKey = privateKeyReader.ReadBignum2(); parsedKey = new ED25519Key(publicKey.Reverse(), unencryptedPrivateKey); break; -#if FEATURE_ECDSA case "ecdsa-sha2-nistp256": case "ecdsa-sha2-nistp384": case "ecdsa-sha2-nistp521": @@ -510,7 +504,6 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) unencryptedPrivateKey = privateKeyReader.ReadBignum2(); parsedKey = new EcdsaKey(curve, publicKey, unencryptedPrivateKey.TrimLeadingZeros()); break; -#endif case "ssh-rsa": var modulus = privateKeyReader.ReadBignum(); //n var exponent = privateKeyReader.ReadBignum(); //e diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index d9399877b..2f39c80ec 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -11,7 +11,7 @@ - FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_REGEX_COMPILE;FEATURE_BINARY_SERIALIZATION;FEATURE_RNG_CREATE;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_STREAM_APM;FEATURE_DNS_SYNC;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_HMAC_RIPEMD160;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_ENCODING_ASCII;FEATURE_ECDSA;FEATURE_TAP + FEATURE_BINARY_SERIALIZATION;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_DNS_SYNC;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_RIPEMD160 @@ -19,6 +19,6 @@ - FEATURE_STRINGBUILDER_CLEAR;FEATURE_HASHALGORITHM_DISPOSE;FEATURE_ENCODING_ASCII;FEATURE_DIAGNOSTICS_TRACESOURCE;FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_MEMORYSTREAM_GETBUFFER;FEATURE_MEMORYSTREAM_TRYGETBUFFER;FEATURE_RNG_CREATE;FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_SOCKET_SYNC;FEATURE_SOCKET_SELECT;FEATURE_SOCKET_POLL;FEATURE_SOCKET_DISPOSE;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP;FEATURE_STREAM_APM;FEATURE_STREAM_TAP;FEATURE_THREAD_COUNTDOWNEVENT;FEATURE_THREAD_TAP;FEATURE_THREAD_THREADPOOL;FEATURE_THREAD_SLEEP;FEATURE_WAITHANDLE_DISPOSE;FEATURE_HASH_MD5;FEATURE_HASH_SHA1_CREATE;FEATURE_HASH_SHA256_CREATE;FEATURE_HASH_SHA384_CREATE;FEATURE_HASH_SHA512_CREATE;FEATURE_HMAC_MD5;FEATURE_HMAC_SHA1;FEATURE_HMAC_SHA256;FEATURE_HMAC_SHA384;FEATURE_HMAC_SHA512;FEATURE_ECDSA;FEATURE_TAP + FEATURE_DIRECTORYINFO_ENUMERATEFILES;FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs index 5dd468b04..50ae6f38d 100644 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs +++ b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/CryptoApiRandomGenerator.cs @@ -9,9 +9,7 @@ internal class CryptoApiRandomGenerator private readonly RandomNumberGenerator rndProv; public CryptoApiRandomGenerator() -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP : this(Abstractions.CryptoAbstraction.CreateRandomNumberGenerator()) -#endif { } @@ -34,15 +32,7 @@ public virtual void AddSeedMaterial(long seed) public virtual void NextBytes(byte[] bytes) { -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP rndProv.GetBytes(bytes); -#else - if (bytes == null) - throw new ArgumentNullException("bytes"); - - var buffer = Windows.Security.Cryptography.CryptographicBuffer.GenerateRandom((uint)bytes.Length); - System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.CopyTo(buffer, bytes); -#endif } public virtual void NextBytes(byte[] bytes, int start, int len) diff --git a/src/Renci.SshNet/Security/Cryptography/Bcrypt.cs b/src/Renci.SshNet/Security/Cryptography/Bcrypt.cs index 837d00318..14f6169a5 100644 --- a/src/Renci.SshNet/Security/Cryptography/Bcrypt.cs +++ b/src/Renci.SshNet/Security/Cryptography/Bcrypt.cs @@ -499,14 +499,10 @@ public static string GenerateSalt(int workFactor) throw new ArgumentOutOfRangeException("workFactor", "The work factor must be between 4 and 31 (inclusive)"); byte[] rnd = new byte[BCRYPT_SALT_LEN]; -#if FEATURE_RNG_CREATE + RandomNumberGenerator rng = RandomNumberGenerator.Create(); -#elif FEATURE_RNG_CSP - RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); -#endif -#if FEATURE_RNG_CREATE || FEATURE_RNG_CSP + rng.GetBytes(rnd); -#endif StringBuilder rs = new StringBuilder(); rs.AppendFormat("$2a${0:00}$", workFactor); diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs index 920614672..b5561b5da 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs @@ -1,5 +1,4 @@ -#if FEATURE_ECDSA -using System; +using System; using Renci.SshNet.Common; using System.Globalization; using System.Security.Cryptography; @@ -186,4 +185,3 @@ protected override int BufferCapacity } } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs index 46f1dcc65..1674a6677 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs @@ -1,5 +1,4 @@ -#if FEATURE_ECDSA -using System; +using System; using System.IO; using System.Text; using System.Runtime.InteropServices; @@ -467,4 +466,3 @@ protected virtual void Dispose(bool disposing) #endregion } } -#endif \ No newline at end of file diff --git a/src/Renci.SshNet/Security/Cryptography/HMACMD5.cs b/src/Renci.SshNet/Security/Cryptography/HMACMD5.cs index 86b246432..cd129fe69 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACMD5.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACMD5.cs @@ -1,6 +1,4 @@ -#if FEATURE_HMAC_MD5 - -using System.Security.Cryptography; +using System.Security.Cryptography; using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -57,5 +55,3 @@ protected override byte[] HashFinal() } } } - -#endif // FEATURE_HMAC_MD5 diff --git a/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs b/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs index d8f47af12..49ad384d4 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs @@ -1,6 +1,4 @@ -#if FEATURE_HMAC_SHA1 - -using System.Security.Cryptography; +using System.Security.Cryptography; using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -57,5 +55,3 @@ protected override byte[] HashFinal() } } } - -#endif // FEATURE_HMAC_SHA1 diff --git a/src/Renci.SshNet/Security/Cryptography/HMACSHA256.cs b/src/Renci.SshNet/Security/Cryptography/HMACSHA256.cs index cb1c31859..2598704e4 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACSHA256.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACSHA256.cs @@ -1,6 +1,4 @@ -#if FEATURE_HMAC_SHA256 - -using System.Security.Cryptography; +using System.Security.Cryptography; using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -58,5 +56,3 @@ protected override byte[] HashFinal() } } } - -#endif // FEATURE_HMAC_SHA256 diff --git a/src/Renci.SshNet/Security/Cryptography/HMACSHA384.cs b/src/Renci.SshNet/Security/Cryptography/HMACSHA384.cs index 142e51ed7..f5f0b26c5 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACSHA384.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACSHA384.cs @@ -1,6 +1,4 @@ -#if FEATURE_HMAC_SHA384 - -using System.Security.Cryptography; +using System.Security.Cryptography; using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -57,5 +55,3 @@ protected override byte[] HashFinal() } } } - -#endif // FEATURE_HMAC_SHA384 diff --git a/src/Renci.SshNet/Security/Cryptography/HMACSHA512.cs b/src/Renci.SshNet/Security/Cryptography/HMACSHA512.cs index a297ed088..72e758155 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACSHA512.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACSHA512.cs @@ -1,6 +1,4 @@ -#if FEATURE_HMAC_SHA512 - -using System.Security.Cryptography; +using System.Security.Cryptography; using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -57,5 +55,3 @@ protected override byte[] HashFinal() } } } - -#endif // FEATURE_HMAC_SHA512 diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs index 0846cb2cd..13764e386 100644 --- a/src/Renci.SshNet/Session.cs +++ b/src/Renci.SshNet/Session.cs @@ -16,9 +16,7 @@ using System.Linq; using Renci.SshNet.Abstractions; using Renci.SshNet.Security.Cryptography; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet { @@ -172,13 +170,11 @@ public class Session : ISession /// private Socket _socket; -#if FEATURE_SOCKET_POLL /// /// Holds an object that is used to ensure only a single thread can read from /// at any given time. /// private readonly object _socketReadLock = new object(); -#endif // FEATURE_SOCKET_POLL /// /// Holds an object that is used to ensure only a single thread can write to @@ -673,7 +669,6 @@ public void Connect() } } -#if FEATURE_TAP /// /// Asynchronously connects to the server. /// @@ -777,7 +772,6 @@ public async Task ConnectAsync(CancellationToken cancellationToken) RegisterMessage("SSH_MSG_CHANNEL_EOF"); RegisterMessage("SSH_MSG_CHANNEL_CLOSE"); } -#endif /// /// Disconnects from the server. @@ -1150,13 +1144,11 @@ private Message ReceiveMessage(Socket socket) byte[] data; uint packetLength; -#if FEATURE_SOCKET_POLL // avoid reading from socket while IsSocketConnected is attempting to determine whether the // socket is still connected by invoking Socket.Poll(...) and subsequently verifying value of // Socket.Available lock (_socketReadLock) { -#endif // FEATURE_SOCKET_POLL // Read first block - which starts with the packet length var firstBlock = new byte[blockSize]; if (TrySocketRead(socket, firstBlock, 0, blockSize) == 0) @@ -1204,9 +1196,7 @@ private Message ReceiveMessage(Socket socket) return null; } } -#if FEATURE_SOCKET_POLL } -#endif // FEATURE_SOCKET_POLL if (_serverCipher != null) { @@ -1767,7 +1757,6 @@ internal static string ToHex(byte[] bytes) #endregion -#if FEATURE_SOCKET_POLL /// /// Gets a value indicating whether the socket is connected. /// @@ -1807,23 +1796,10 @@ internal static string ToHex(byte[] bytes) /// we synchronize reads from the . /// /// -#else - /// - /// Gets a value indicating whether the socket is connected. - /// - /// - /// true if the socket is connected; otherwise, false. - /// - /// - /// We verify whether is true. However, this only returns the state - /// of the socket as of the last I/O operation. - /// -#endif private bool IsSocketConnected() { lock (_socketDisposeLock) { -#if FEATURE_SOCKET_POLL if (!_socket.IsConnected()) { return false; @@ -1834,9 +1810,6 @@ private bool IsSocketConnected() var connectionClosedOrDataAvailable = _socket.Poll(0, SelectMode.SelectRead); return !(connectionClosedOrDataAvailable && _socket.Available == 0); } -#else - return _socket.IsConnected(); -#endif // FEATURE_SOCKET_POLL } } @@ -1915,10 +1888,8 @@ private void MessageListener() break; } -#if FEATURE_SOCKET_POLL || FEATURE_SOCKET_SELECT try { -#if FEATURE_SOCKET_POLL // Block until either data is available or the socket is closed var connectionClosedOrDataAvailable = socket.Poll(-1, SelectMode.SelectRead); if (connectionClosedOrDataAvailable && socket.Available == 0) @@ -1926,43 +1897,6 @@ private void MessageListener() // connection with SSH server was closed or connection was reset break; } -#elif FEATURE_SOCKET_SELECT - var readSockets = new List { socket }; - - // if the socket is already disposed when Select is invoked, then a SocketException - // stating "An operation was attempted on something that is not a socket" is thrown; - // we attempt to avoid this exception by having an IsConnected() that can break the - // message loop - // - // note that there's no guarantee that the socket will not be disposed between the - // IsConnected() check and the Select invocation; we can't take a "dispose" lock - // that includes the Select invocation as we want Dispose() to be able to interrupt - // the Select - - // perform a blocking select to determine whether there's is data available to be - // read; we do not use a blocking read to allow us to use Socket.Poll to determine - // if the connection is still available (in IsSocketConnected) - - Socket.Select(readSockets, null, null, -1); - - // the Select invocation will be interrupted in one of the following conditions: - // * data is available to be read - // => the socket will not be removed from "readSockets" - // * the socket connection is closed during the Select invocation - // => the socket will be removed from "readSockets" - // * the socket is disposed during the Select invocation - // => the socket will not be removed from "readSocket" - // - // since we handle the second and third condition the same way and Socket.Connected - // allows us to check for both conditions, we use that instead of both checking for - // the removal from "readSockets" and the Connection check - if (!socket.IsConnected()) - { - // connection with SSH server was closed or socket was disposed; - // break out of the message loop - break; - } -#endif // FEATURE_SOCKET_SELECT } catch (ObjectDisposedException) { @@ -1972,7 +1906,6 @@ private void MessageListener() // * a SSH_MSG_DISCONNECT received from server break; } -#endif // FEATURE_SOCKET_POLL || FEATURE_SOCKET_SELECT var message = ReceiveMessage(socket); if (message == null) diff --git a/src/Renci.SshNet/Sftp/ISftpSession.cs b/src/Renci.SshNet/Sftp/ISftpSession.cs index 4a3648bd4..8971bd571 100644 --- a/src/Renci.SshNet/Sftp/ISftpSession.cs +++ b/src/Renci.SshNet/Sftp/ISftpSession.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Threading; using Renci.SshNet.Sftp.Responses; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet.Sftp { @@ -41,9 +39,7 @@ internal interface ISftpSession : ISubsystemSession /// string GetCanonicalPath(string path); -#if FEATURE_TAP Task GetCanonicalPathAsync(string path, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_FSTAT request. @@ -55,9 +51,7 @@ internal interface ISftpSession : ISubsystemSession /// SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError); -#if FEATURE_TAP Task RequestFStatAsync(byte[] handle, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_STAT request. @@ -135,9 +129,7 @@ internal interface ISftpSession : ISubsystemSession /// File handle. byte[] RequestOpen(string path, Flags flags, bool nullOnError = false); -#if FEATURE_TAP Task RequestOpenAsync(string path, Flags flags, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_OPEN request @@ -173,9 +165,7 @@ internal interface ISftpSession : ISubsystemSession /// File handle. byte[] RequestOpenDir(string path, bool nullOnError = false); -#if FEATURE_TAP Task RequestOpenDirAsync(string path, CancellationToken cancellationToken); -#endif /// /// Performs posix-rename@openssh.com extended request. @@ -220,9 +210,7 @@ internal interface ISftpSession : ISubsystemSession /// is null. byte[] EndRead(SftpReadAsyncResult asyncResult); -#if FEATURE_TAP Task RequestReadAsync(byte[] handle, ulong offset, uint length, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_READDIR request @@ -231,9 +219,7 @@ internal interface ISftpSession : ISubsystemSession /// KeyValuePair[] RequestReadDir(byte[] handle); -#if FEATURE_TAP Task[]> RequestReadDirAsync(byte[] handle, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_REALPATH request. @@ -262,9 +248,7 @@ internal interface ISftpSession : ISubsystemSession /// The path. void RequestRemove(string path); -#if FEATURE_TAP Task RequestRemoveAsync(string path, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_RENAME request. @@ -273,9 +257,7 @@ internal interface ISftpSession : ISubsystemSession /// The new path. void RequestRename(string oldPath, string newPath); -#if FEATURE_TAP Task RequestRenameAsync(string oldPath, string newPath, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_RMDIR request. @@ -298,9 +280,7 @@ internal interface ISftpSession : ISubsystemSession /// SftpFileSytemInformation RequestStatVfs(string path, bool nullOnError = false); -#if FEATURE_TAP Task RequestStatVfsAsync(string path, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_SYMLINK request. @@ -334,9 +314,7 @@ void RequestWrite(byte[] handle, AutoResetEvent wait, Action writeCompleted = null); -#if FEATURE_TAP Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] data, int offset, int length, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_CLOSE request. @@ -344,9 +322,7 @@ void RequestWrite(byte[] handle, /// The handle. void RequestClose(byte[] handle); -#if FEATURE_TAP Task RequestCloseAsync(byte[] handle, CancellationToken cancellationToken); -#endif /// /// Performs SSH_FXP_CLOSE request. diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index b47023687..a266b35b8 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -3,9 +3,7 @@ using System.Threading; using System.Diagnostics.CodeAnalysis; using Renci.SshNet.Common; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet.Sftp { @@ -293,7 +291,6 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc } } -#if FEATURE_TAP internal static async Task OpenAsync(ISftpSession session, string path, FileMode mode, FileAccess access, int bufferSize, CancellationToken cancellationToken) { if (session == null) @@ -390,7 +387,6 @@ internal static async Task OpenAsync(ISftpSession session, strin return new SftpFileStream(session, path, access, bufferSize, handle, position); } -#endif /// /// Releases unmanaged resources and performs other cleanup operations before the @@ -423,7 +419,6 @@ public override void Flush() } } -#if FEATURE_TAP /// /// Asynchronously clears all buffers for this stream and causes any buffered data to be written to the file. /// @@ -446,7 +441,6 @@ public override Task FlushAsync(CancellationToken cancellationToken) return Task.CompletedTask; } -#endif /// /// Reads a sequence of bytes from the current stream and advances the position within the stream by the @@ -588,7 +582,6 @@ public override int Read(byte[] buffer, int offset, int count) return readLen; } -#if FEATURE_TAP /// /// Asynchronously reads a sequence of bytes from the current stream and advances the position within the stream by the /// number of bytes read. @@ -700,7 +693,6 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, // return the number of bytes that were read to the caller. return readLen; } -#endif /// /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. @@ -986,7 +978,7 @@ public override void Write(byte[] buffer, int offset, int count) } } -#if FEATURE_TAP + /// /// Asynchronously writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. /// @@ -1062,7 +1054,6 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc _bufferPosition = 0; } } -#endif /// /// Writes a byte to the current position in the stream and advances the position within the stream by one byte. @@ -1181,7 +1172,6 @@ private void FlushWriteBuffer() } } -#if FEATURE_TAP private async Task FlushWriteBufferAsync(CancellationToken cancellationToken) { if (_bufferPosition > 0) @@ -1190,7 +1180,6 @@ private async Task FlushWriteBufferAsync(CancellationToken cancellationToken) _bufferPosition = 0; } } -#endif /// /// Setups the read. diff --git a/src/Renci.SshNet/Sftp/SftpSession.cs b/src/Renci.SshNet/Sftp/SftpSession.cs index c33c70e34..dd38bd36e 100644 --- a/src/Renci.SshNet/Sftp/SftpSession.cs +++ b/src/Renci.SshNet/Sftp/SftpSession.cs @@ -6,9 +6,7 @@ using System.Globalization; using Renci.SshNet.Sftp.Responses; using Renci.SshNet.Sftp.Requests; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet.Sftp { @@ -139,7 +137,6 @@ public string GetCanonicalPath(string path) return string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", canonizedPath, slash, pathParts[pathParts.Length - 1]); } -#if FEATURE_TAP public async Task GetCanonicalPathAsync(string path, CancellationToken cancellationToken) { var fullPath = GetFullRemotePath(path); @@ -185,7 +182,6 @@ public async Task GetCanonicalPathAsync(string path, CancellationToken c slash = "/"; return canonizedPath + slash + pathParts[pathParts.Length - 1]; } -#endif public ISftpFileReader CreateFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, int maxPendingReads, long? fileSize) { @@ -436,7 +432,6 @@ public byte[] RequestOpen(string path, Flags flags, bool nullOnError = false) return handle; } -#if FEATURE_TAP public async Task RequestOpenAsync(string path, Flags flags, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -452,7 +447,6 @@ public async Task RequestOpenAsync(string path, Flags flags, Cancellatio return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_OPEN request @@ -541,7 +535,6 @@ public void RequestClose(byte[] handle) } } -#if FEATURE_TAP public async Task RequestCloseAsync(byte[] handle, CancellationToken cancellationToken) { TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -566,8 +559,6 @@ public async Task RequestCloseAsync(byte[] handle, CancellationToken cancellatio await tcs.Task.ConfigureAwait(false); } } -#endif - /// /// Performs SSH_FXP_CLOSE request. @@ -732,7 +723,6 @@ public byte[] RequestRead(byte[] handle, ulong offset, uint length) return data; } -#if FEATURE_TAP public async Task RequestReadAsync(byte[] handle, ulong offset, uint length, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -758,7 +748,6 @@ public async Task RequestReadAsync(byte[] handle, ulong offset, uint len return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_WRITE request. @@ -804,7 +793,6 @@ public void RequestWrite(byte[] handle, } } -#if FEATURE_TAP public async Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] data, int offset, int length, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -829,7 +817,6 @@ public async Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] da await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_LSTAT request. @@ -963,7 +950,6 @@ public SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError) return attributes; } -#if FEATURE_TAP public async Task RequestFStatAsync(byte[] handle, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -979,7 +965,6 @@ public async Task RequestFStatAsync(byte[] handle, Cancellat return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_SETSTAT request. @@ -1078,7 +1063,6 @@ public byte[] RequestOpenDir(string path, bool nullOnError = false) return handle; } -#if FEATURE_TAP public async Task RequestOpenDirAsync(string path, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1094,7 +1078,6 @@ public async Task RequestOpenDirAsync(string path, CancellationToken can return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_READDIR request @@ -1137,7 +1120,6 @@ public KeyValuePair[] RequestReadDir(byte[] handle) return result; } -#if FEATURE_TAP public async Task[]> RequestReadDirAsync(byte[] handle, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1163,8 +1145,6 @@ public async Task[]> RequestReadDirAsyn return await tcs.Task.ConfigureAwait(false); } } -#endif - /// /// Performs SSH_FXP_REMOVE request. @@ -1194,7 +1174,6 @@ public void RequestRemove(string path) } } -#if FEATURE_TAP public async Task RequestRemoveAsync(string path, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1219,8 +1198,6 @@ public async Task RequestRemoveAsync(string path, CancellationToken cancellation await tcs.Task.ConfigureAwait(false); } } -#endif - /// /// Performs SSH_FXP_MKDIR request. @@ -1319,7 +1296,6 @@ internal KeyValuePair[] RequestRealPath(string path, return result; } -#if FEATURE_TAP internal async Task[]> RequestRealPathAsync(string path, bool nullOnError, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1345,7 +1321,6 @@ internal async Task[]> RequestRealPathA return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_REALPATH request. @@ -1528,8 +1503,6 @@ public void RequestRename(string oldPath, string newPath) } } - -#if FEATURE_TAP public async Task RequestRenameAsync(string oldPath, string newPath, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -1554,7 +1527,6 @@ public async Task RequestRenameAsync(string oldPath, string newPath, Cancellatio await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs SSH_FXP_READLINK request. @@ -1722,8 +1694,6 @@ public SftpFileSytemInformation RequestStatVfs(string path, bool nullOnError = f return information; } - -#if FEATURE_TAP public async Task RequestStatVfsAsync(string path, CancellationToken cancellationToken) { if (ProtocolVersion < 3) @@ -1744,7 +1714,6 @@ public async Task RequestStatVfsAsync(string path, Can return await tcs.Task.ConfigureAwait(false); } } -#endif /// /// Performs fstatvfs@openssh.com extended request. diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs index a7ce34538..2705382ad 100644 --- a/src/Renci.SshNet/SftpClient.cs +++ b/src/Renci.SshNet/SftpClient.cs @@ -10,9 +10,7 @@ using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Sftp; -#if FEATURE_TAP using System.Threading.Tasks; -#endif namespace Renci.SshNet { @@ -376,7 +374,6 @@ public void DeleteFile(string path) _sftpSession.RequestRemove(fullPath); } -#if FEATURE_TAP /// /// Asynchronously deletes remote file specified by path. /// @@ -401,7 +398,6 @@ public async Task DeleteFileAsync(string path, CancellationToken cancellationTok var fullPath = await _sftpSession.GetCanonicalPathAsync(path, cancellationToken).ConfigureAwait(false); await _sftpSession.RequestRemoveAsync(fullPath, cancellationToken).ConfigureAwait(false); } -#endif /// /// Renames remote file from old path to new path. @@ -418,7 +414,6 @@ public void RenameFile(string oldPath, string newPath) RenameFile(oldPath, newPath, false); } -#if FEATURE_TAP /// /// Asynchronously renames remote file from old path to new path. /// @@ -446,7 +441,6 @@ public async Task RenameFileAsync(string oldPath, string newPath, CancellationTo var newFullPath = await _sftpSession.GetCanonicalPathAsync(newPath, cancellationToken).ConfigureAwait(false); await _sftpSession.RequestRenameAsync(oldFullPath, newFullPath, cancellationToken).ConfigureAwait(false); } -#endif /// /// Renames remote file from old path to new path. @@ -536,8 +530,6 @@ public IEnumerable ListDirectory(string path, Action listCallbac return InternalListDirectory(path, listCallback); } -#if FEATURE_TAP - /// /// Asynchronously retrieves list of files in remote directory. /// @@ -594,8 +586,6 @@ public async Task> ListDirectoryAsync(string path, Cancel return result; } -#endif - /// /// Begins an asynchronous operation of retrieving list of files in remote directory. /// @@ -1129,7 +1119,6 @@ public SftpFileSytemInformation GetStatus(string path) return _sftpSession.RequestStatVfs(fullPath); } -#if FEATURE_TAP /// /// Asynchronously gets status using statvfs@openssh.com request. /// @@ -1154,7 +1143,6 @@ public async Task GetStatusAsync(string path, Cancella var fullPath = await _sftpSession.GetCanonicalPathAsync(path, cancellationToken).ConfigureAwait(false); return await _sftpSession.RequestStatVfsAsync(fullPath, cancellationToken).ConfigureAwait(false); } -#endif #region File Methods @@ -1503,7 +1491,6 @@ public SftpFileStream Open(string path, FileMode mode, FileAccess access) return new SftpFileStream(_sftpSession, path, mode, access, (int) _bufferSize); } -#if FEATURE_TAP /// /// Asynchronously opens a on the specified path, with the specified mode and access. /// @@ -1529,7 +1516,6 @@ public Task OpenAsync(string path, FileMode mode, FileAccess acc return SftpFileStream.OpenAsync(_sftpSession, path, mode, access, (int)_bufferSize, cancellationToken); } -#endif /// /// Opens an existing file for reading. diff --git a/src/Renci.SshNet/Shell.cs b/src/Renci.SshNet/Shell.cs index c508be896..3e68e6b12 100644 --- a/src/Renci.SshNet/Shell.cs +++ b/src/Renci.SshNet/Shell.cs @@ -129,7 +129,6 @@ public void Start() while (_channel.IsOpen) { -#if FEATURE_STREAM_TAP var readTask = _input.ReadAsync(buffer, 0, buffer.Length); var readWaitHandle = ((IAsyncResult) readTask).AsyncWaitHandle; @@ -139,24 +138,7 @@ public void Start() _channel.SendData(buffer, 0, read); continue; } -#elif FEATURE_STREAM_APM - var asyncResult = _input.BeginRead(buffer, 0, buffer.Length, result => - { - // If input stream is closed and disposed already don't finish reading the stream - if (_input == null) - return; - var read = _input.EndRead(result); - _channel.SendData(buffer, 0, read); - }, null); - - WaitHandle.WaitAny(new[] { asyncResult.AsyncWaitHandle, _channelClosedWaitHandle }); - - if (asyncResult.IsCompleted) - continue; -#else - #error Async receive is not implemented. -#endif break; } } From b4d9e816ffd310576a37a48d0ed457b588ccf2ac Mon Sep 17 00:00:00 2001 From: drieseng Date: Mon, 22 May 2023 09:06:20 +0200 Subject: [PATCH 19/19] Fix some (lots of) issues reported by analyzers. --- .editorconfig_soon | 1235 +++++++++++++++++ Directory.Build.props | 48 + .../Classes/Common/ObjectIdentifierTest.cs | 39 +- ...ectionClosedByServer_NoDataSentByServer.cs | 12 +- .../Classes/MessageEventArgsTest.cs | 1 - .../Classes/Security/Cryptography/HMacTest.cs | 1 - .../Sftp/SftpStatVfsResponseBuilder.cs | 22 +- .../Common/AsyncSocketListener.cs | 2 +- .../Renci.SshNet.Tests.csproj | 15 +- src/Renci.SshNet.sln | 24 +- src/Renci.SshNet/.editorconfig | 25 + .../Abstractions/CryptoAbstraction.cs | 2 +- .../Abstractions/SocketAbstraction.cs | 43 +- .../Abstractions/SocketExtensions.cs | 40 +- .../Abstractions/ThreadAbstraction.cs | 12 +- src/Renci.SshNet/AuthenticationMethod.cs | 11 +- src/Renci.SshNet/BaseClient.cs | 94 +- src/Renci.SshNet/Channels/Channel.cs | 147 +- .../Channels/ChannelDirectTcpip.cs | 38 +- .../Channels/ChannelForwardedTcpip.cs | 6 + src/Renci.SshNet/Channels/ChannelSession.cs | 60 +- src/Renci.SshNet/Channels/ClientChannel.cs | 17 +- src/Renci.SshNet/Channels/ServerChannel.cs | 14 +- src/Renci.SshNet/CipherInfo.cs | 2 +- src/Renci.SshNet/ClientAuthentication.cs | 29 +- src/Renci.SshNet/CommandAsyncResult.cs | 26 +- src/Renci.SshNet/Common/AsyncResult.cs | 98 +- .../Common/AuthenticationBannerEventArgs.cs | 2 +- .../Common/AuthenticationEventArgs.cs | 10 +- .../AuthenticationPasswordChangeEventArgs.cs | 18 +- .../Common/AuthenticationPrompt.cs | 36 +- .../Common/AuthenticationPromptEventArgs.cs | 32 +- src/Renci.SshNet/Common/BigInteger.cs | 1102 +++++++++++---- .../Common/ChannelDataEventArgs.cs | 12 +- src/Renci.SshNet/Common/ChannelEventArgs.cs | 13 +- .../Common/ChannelExtendedDataEventArgs.cs | 10 +- .../Common/ChannelOpenConfirmedEventArgs.cs | 6 +- .../Common/ChannelOpenFailedEventArgs.cs | 32 +- .../Common/ChannelRequestEventArgs.cs | 16 +- src/Renci.SshNet/Common/DerData.cs | 85 +- src/Renci.SshNet/Common/ExceptionEventArgs.cs | 13 +- src/Renci.SshNet/Common/Extensions.cs | 86 +- src/Renci.SshNet/Common/HostKeyEventArgs.cs | 5 +- .../Common/NetConfServerException.cs | 4 +- src/Renci.SshNet/Common/ObjectIdentifier.cs | 16 +- src/Renci.SshNet/Common/PacketDump.cs | 40 +- src/Renci.SshNet/Common/PipeStream.cs | 206 +-- .../Common/PortForwardEventArgs.cs | 30 +- src/Renci.SshNet/Common/PosixPath.cs | 58 +- src/Renci.SshNet/Common/ProxyException.cs | 10 +- .../Common/ScpDownloadEventArgs.cs | 30 +- src/Renci.SshNet/Common/ScpException.cs | 4 +- src/Renci.SshNet/Common/ScpUploadEventArgs.cs | 30 +- src/Renci.SshNet/Common/SemaphoreLight.cs | 56 +- .../Common/SftpPathNotFoundException.cs | 4 +- .../Common/SftpPermissionDeniedException.cs | 4 +- src/Renci.SshNet/Common/ShellDataEventArgs.cs | 22 +- .../Common/SshAuthenticationException.cs | 6 +- src/Renci.SshNet/Common/SshData.cs | 60 +- src/Renci.SshNet/Common/SshDataStream.cs | 60 +- .../Common/SshOperationTimeoutException.cs | 4 +- .../SshPassPhraseNullOrEmptyException.cs | 8 +- src/Renci.SshNet/Common/TerminalModes.cs | 26 +- src/Renci.SshNet/Compression/Compressor.cs | 23 +- src/Renci.SshNet/Connection/ConnectorBase.cs | 18 +- .../Connection/DirectConnector.cs | 3 +- src/Renci.SshNet/Connection/HttpConnector.cs | 38 +- .../Connection/ProtocolVersionExchange.cs | 129 +- src/Renci.SshNet/Connection/ProxyConnector.cs | 8 +- .../Connection/Socks4Connector.cs | 18 +- .../Connection/Socks5Connector.cs | 48 +- .../Connection/SshIdentification.cs | 33 +- src/Renci.SshNet/ConnectionInfo.cs | 194 +-- src/Renci.SshNet/ExpectAction.cs | 18 +- src/Renci.SshNet/ExpectAsyncResult.cs | 9 +- src/Renci.SshNet/ForwardedPort.cs | 26 +- src/Renci.SshNet/ForwardedPortDynamic.NET.cs | 32 +- src/Renci.SshNet/ForwardedPortDynamic.cs | 49 +- src/Renci.SshNet/ForwardedPortLocal.NET.cs | 23 +- src/Renci.SshNet/ForwardedPortLocal.cs | 53 +- src/Renci.SshNet/ForwardedPortRemote.cs | 72 +- src/Renci.SshNet/ForwardedPortStatus.cs | 24 +- src/Renci.SshNet/IBaseClient.cs | 7 +- src/Renci.SshNet/IConnectionInfo.cs | 7 +- src/Renci.SshNet/IRemotePathTransformation.cs | 2 - src/Renci.SshNet/IServiceFactory.cs | 4 +- src/Renci.SshNet/ISession.cs | 3 +- src/Renci.SshNet/ISftpClient.cs | 9 +- ...KeyboardInteractiveAuthenticationMethod.cs | 48 +- .../KeyboardInteractiveConnectionInfo.cs | 37 +- src/Renci.SshNet/MessageEventArgs.cs | 8 +- .../Authentication/RequestMessageHost.cs | 20 +- .../Messages/Connection/ChannelDataMessage.cs | 16 +- .../Messages/Connection/ChannelMessage.cs | 8 +- .../ChannelOpen/ChannelOpenMessage.cs | 6 +- .../ChannelOpen/DirectTcpipChannelInfo.cs | 2 +- .../ChannelOpen/ForwardedTcpipChannelInfo.cs | 2 +- .../ChannelOpen/SessionChannelOpenInfo.cs | 2 +- .../ChannelOpen/X11ChannelOpenInfo.cs | 2 +- .../ChannelRequest/BreakRequestInfo.cs | 2 +- .../ChannelRequest/ExecRequestInfo.cs | 13 +- .../ChannelRequest/PseudoTerminalInfo.cs | 13 +- .../ChannelRequest/ShellRequestInfo.cs | 2 +- .../ChannelRequest/SignalRequestInfo.cs | 2 +- .../ChannelRequest/SubsystemRequestInfo.cs | 2 +- .../ChannelRequest/WindowChangeRequestInfo.cs | 2 +- .../X11ForwardingRequestInfo.cs | 8 +- .../ChannelRequest/XonXoffRequestInfo.cs | 4 +- .../Connection/ChannelWindowAdjustMessage.cs | 3 +- .../Connection/RequestFailureMessage.cs | 3 +- .../Connection/RequestSuccessMessage.cs | 9 +- .../TcpIpForwardGlobalRequestMessage.cs | 2 +- src/Renci.SshNet/Messages/Message.cs | 30 +- .../Messages/Transport/IgnoreMessage.cs | 4 +- .../KeyExchangeDhGroupExchangeInit.cs | 2 +- .../KeyExchangeDhGroupExchangeReply.cs | 12 +- .../KeyExchangeDhGroupExchangeRequest.cs | 8 +- .../Transport/KeyExchangeDhInitMessage.cs | 2 +- .../Transport/KeyExchangeEcdhInitMessage.cs | 4 +- src/Renci.SshNet/NetConfClient.cs | 52 +- src/Renci.SshNet/Netconf/NetConfSession.cs | 63 +- src/Renci.SshNet/NoneAuthenticationMethod.cs | 38 +- .../PasswordAuthenticationMethod.cs | 60 +- src/Renci.SshNet/PasswordConnectionInfo.cs | 33 +- .../PrivateKeyAuthenticationMethod.cs | 55 +- src/Renci.SshNet/PrivateKeyConnectionInfo.cs | 42 +- src/Renci.SshNet/PrivateKeyFile.cs | 169 ++- src/Renci.SshNet/Properties/AssemblyInfo.cs | 2 +- .../RemotePathDoubleQuoteTransformation.cs | 15 +- .../RemotePathNoneTransformation.cs | 2 +- .../RemotePathShellQuoteTransformation.cs | 56 +- src/Renci.SshNet/Renci.SshNet.csproj | 5 - src/Renci.SshNet/ScpClient.NET.cs | 102 +- src/Renci.SshNet/ScpClient.cs | 73 +- .../Security/BouncyCastle/.editorconfig | 7 + .../crypto/prng/IRandomGenerator.cs | 2 +- .../math/ec/endo/GlvEndomorphism.cs | 2 +- .../Security/Chaos.NaCl/.editorconfig | 7 + .../Security/Cryptography/.editorconfig | 12 + .../Security/Cryptography/BlockCipher.cs | 1 + .../Cryptography/CipherDigitalSignature.cs | 12 +- .../Cryptography/Ciphers/AesCipher.cs | 34 +- .../Cryptography/Ciphers/Arc4Cipher.cs | 7 +- .../Cryptography/Ciphers/BlowfishCipher.cs | 3 + .../Cryptography/Ciphers/DesCipher.cs | 58 +- .../Ciphers/Modes/CbcCipherMode.cs | 20 +- .../Ciphers/Modes/CfbCipherMode.cs | 20 +- .../Ciphers/Modes/CtrCipherMode.cs | 24 +- .../Ciphers/Modes/OfbCipherMode.cs | 20 +- .../Ciphers/Paddings/PKCS5Padding.cs | 4 +- .../Ciphers/Paddings/PKCS7Padding.cs | 2 + .../Cryptography/Ciphers/RsaCipher.cs | 26 +- .../Cryptography/Ciphers/SerpentCipher.cs | 959 +++++++++---- .../Cryptography/Ciphers/TripleDesCipher.cs | 12 +- .../Cryptography/Ciphers/TwofishCipher.cs | 35 +- .../Cryptography/DsaDigitalSignature.cs | 71 +- .../Security/Cryptography/DsaKey.cs | 30 +- .../Cryptography/ED25519DigitalSignature.cs | 22 +- .../Security/Cryptography/ED25519Key.cs | 32 +- .../Cryptography/EcdsaDigitalSignature.cs | 32 +- .../Security/Cryptography/EcdsaKey.cs | 120 +- .../Security/Cryptography/HMACSHA1.cs | 5 +- src/Renci.SshNet/Security/Cryptography/Key.cs | 13 +- .../Security/Cryptography/RsaKey.cs | 3 +- .../Security/Cryptography/SymmetricCipher.cs | 4 +- src/Renci.SshNet/Security/IKeyExchange.cs | 1 + src/Renci.SshNet/Security/KeyExchange.cs | 100 +- .../Security/KeyExchangeDiffieHellman.cs | 20 +- .../KeyExchangeDiffieHellmanGroup14Sha1.cs | 6 +- .../KeyExchangeDiffieHellmanGroup14Sha256.cs | 6 +- .../KeyExchangeDiffieHellmanGroup16Sha512.cs | 68 +- .../KeyExchangeDiffieHellmanGroup1Sha1.cs | 2 +- ...yExchangeDiffieHellmanGroupExchangeSha1.cs | 4 +- ...xchangeDiffieHellmanGroupExchangeSha256.cs | 4 +- ...changeDiffieHellmanGroupExchangeShaBase.cs | 6 +- .../KeyExchangeDiffieHellmanGroupSha1.cs | 2 +- .../KeyExchangeDiffieHellmanGroupSha256.cs | 4 +- .../KeyExchangeDiffieHellmanGroupSha512.cs | 4 +- .../KeyExchangeDiffieHellmanGroupShaBase.cs | 52 +- src/Renci.SshNet/Security/KeyExchangeEC.cs | 8 +- .../Security/KeyExchangeECCurve25519.cs | 10 +- src/Renci.SshNet/Security/KeyExchangeECDH.cs | 30 +- .../Security/KeyExchangeECDH256.cs | 6 +- .../Security/KeyExchangeECDH384.cs | 4 +- .../Security/KeyExchangeECDH521.cs | 6 +- src/Renci.SshNet/Security/KeyExchangeHash.cs | 7 +- src/Renci.SshNet/Security/KeyHostAlgorithm.cs | 13 +- src/Renci.SshNet/ServiceFactory.cs | 31 +- src/Renci.SshNet/Session.cs | 456 +++--- src/Renci.SshNet/Sftp/ISftpFile.cs | 37 +- src/Renci.SshNet/Sftp/ISftpSession.cs | 15 +- .../ExtendedRequests/FStatVfsRequest.cs | 3 +- .../ExtendedRequests/HardLinkRequest.cs | 4 +- .../ExtendedRequests/PosixRenameRequest.cs | 10 +- .../ExtendedRequests/StatVfsRequest.cs | 10 +- .../Sftp/Requests/SftpBlockRequest.cs | 7 +- .../Sftp/Requests/SftpCloseRequest.cs | 2 +- .../Sftp/Requests/SftpFSetStatRequest.cs | 9 +- .../Sftp/Requests/SftpFStatRequest.cs | 6 +- .../Sftp/Requests/SftpInitRequest.cs | 2 +- .../Sftp/Requests/SftpLStatRequest.cs | 7 +- .../Sftp/Requests/SftpLinkRequest.cs | 9 +- .../Sftp/Requests/SftpMkDirRequest.cs | 3 +- .../Sftp/Requests/SftpOpenDirRequest.cs | 8 +- .../Sftp/Requests/SftpOpenRequest.cs | 11 +- .../Sftp/Requests/SftpReadDirRequest.cs | 6 +- .../Sftp/Requests/SftpReadLinkRequest.cs | 10 +- .../Sftp/Requests/SftpReadRequest.cs | 10 +- .../Sftp/Requests/SftpRealPathRequest.cs | 15 +- .../Sftp/Requests/SftpRemoveRequest.cs | 2 +- .../Sftp/Requests/SftpRenameRequest.cs | 2 +- src/Renci.SshNet/Sftp/Requests/SftpRequest.cs | 10 +- .../Sftp/Requests/SftpRmDirRequest.cs | 2 +- .../Sftp/Requests/SftpSetStatRequest.cs | 2 +- .../Sftp/Requests/SftpStatRequest.cs | 11 +- .../Sftp/Requests/SftpSymLinkRequest.cs | 2 +- .../Sftp/Requests/SftpUnblockRequest.cs | 6 +- .../Sftp/Requests/SftpWriteRequest.cs | 4 +- .../ExtendedReplies/StatVfsReplyInfo.cs | 4 +- .../Sftp/Responses/SftpAttrsResponse.cs | 3 +- .../Sftp/Responses/SftpDataResponse.cs | 2 +- .../Sftp/Responses/SftpHandleResponse.cs | 2 +- .../Sftp/Responses/SftpNameResponse.cs | 12 +- .../Sftp/Responses/SftpStatusResponse.cs | 2 +- .../Sftp/Responses/SftpVersionResponse.cs | 6 +- src/Renci.SshNet/Sftp/SFtpStatAsyncResult.cs | 10 +- src/Renci.SshNet/Sftp/SftpCloseAsyncResult.cs | 10 +- src/Renci.SshNet/Sftp/SftpFile.cs | 83 +- src/Renci.SshNet/Sftp/SftpFileAttributes.cs | 252 ++-- src/Renci.SshNet/Sftp/SftpFileReader.cs | 121 +- src/Renci.SshNet/Sftp/SftpFileStream.cs | 272 ++-- .../Sftp/SftpListDirectoryAsyncResult.cs | 6 +- src/Renci.SshNet/Sftp/SftpMessage.cs | 7 +- src/Renci.SshNet/Sftp/SftpMessageTypes.cs | 91 +- src/Renci.SshNet/Sftp/SftpOpenAsyncResult.cs | 10 +- src/Renci.SshNet/Sftp/SftpReadAsyncResult.cs | 10 +- .../Sftp/SftpRealPathAsyncResult.cs | 10 +- src/Renci.SshNet/Sftp/SftpResponseFactory.cs | 3 +- src/Renci.SshNet/Sftp/SftpSession.cs | 1141 ++++++++------- .../SftpSynchronizeDirectoriesAsyncResult.cs | 7 +- .../Sftp/SftpUploadAsyncResult.cs | 5 +- src/Renci.SshNet/Shell.cs | 88 +- src/Renci.SshNet/ShellStream.cs | 160 ++- src/Renci.SshNet/SshClient.cs | 50 +- src/Renci.SshNet/SshCommand.cs | 145 +- src/Renci.SshNet/SshMessageFactory.cs | 107 +- src/Renci.SshNet/SubsystemSession.cs | 72 +- stylecop.json | 25 + test/.editorconfig | 111 ++ test/Directory.Build.props | 16 + 250 files changed, 7541 insertions(+), 4090 deletions(-) create mode 100644 .editorconfig_soon create mode 100644 Directory.Build.props create mode 100644 src/Renci.SshNet/.editorconfig create mode 100644 src/Renci.SshNet/Security/BouncyCastle/.editorconfig create mode 100644 src/Renci.SshNet/Security/Chaos.NaCl/.editorconfig create mode 100644 src/Renci.SshNet/Security/Cryptography/.editorconfig create mode 100644 stylecop.json create mode 100644 test/.editorconfig create mode 100644 test/Directory.Build.props diff --git a/.editorconfig_soon b/.editorconfig_soon new file mode 100644 index 000000000..d0edd58e3 --- /dev/null +++ b/.editorconfig_soon @@ -0,0 +1,1235 @@ +// Avoid looking for .editorconfig files in parent directories +root=true + +[*] + +insert_final_newline = true +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = crlf + +[*.cs] + +#### Sonar rules #### + +# S101: Types should be named in PascalCase +# https://rules.sonarsource.com/csharp/RSPEC-101 +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.S101.severity = none + +# S112: General exceptions should never be thrown +# https://rules.sonarsource.com/csharp/RSPEC-112 +# +# This is a duplicate of CA2201 and MA0012. +dotnet_diagnostic.S112.severity = none + +# S907: Remove use of 'goto' +# https://rules.sonarsource.com/csharp/RSPEC-907 +# +# Limited use of 'goto' is accepted when performance is critical. +dotnet_diagnostic.S907.severity = none + +# S1066: Collapsible "if" statements should be merged +# https://rules.sonarsource.com/csharp/RSPEC-1066 +# +dotnet_diagnostic.S1066.severity = none + +# S1075: URIs should not be hardcoded +# https://rules.sonarsource.com/csharp/RSPEC-1075 +# +# The rule reports false positives for XML namespaces. +dotnet_diagnostic.S1075.severity = none + +# S1104: Fields should not have public accessibility +# https://rules.sonarsource.com/csharp/RSPEC-1104 +# +# This is a duplicate of SA1401 and CA1051. +dotnet_diagnostic.S1104.severity = none + +# S1125: Boolean literals should not be redundant +# https://rules.sonarsource.com/csharp/RSPEC-1125 +# +# This is a duplicate of MA0073. +dotnet_diagnostic.S1125.severity = none + +# S1135: Track uses of "TODO" tags +# +# This is a duplicate of MA0026. +dotnet_diagnostic.S1135.severity = none + +# S1168: Empty arrays and collections should be returned instead of null +# https://rules.sonarsource.com/csharp/RSPEC-1168 +# +# We sometimes return null to avoid allocating an empty List. +dotnet_diagnostic.S1168.severity = none + +# S1172: Unused method parameters should be removed +# https://rules.sonarsource.com/csharp/RSPEC-1172 +# +# This is a duplicate of IDE0060. +dotnet_diagnostic.S1172.severity = none + +# S1481: Unused local variables should be removed +# https://rules.sonarsource.com/csharp/RSPEC-1481 +# +# This is a duplicate of IDE0059. +dotnet_diagnostic.S1481.severity = none + +# S2259: Null pointers should not be dereferenced +# https://rules.sonarsource.com/csharp/RSPEC-2259 +# +# The analysis is not precise enough, leading to false positives. +dotnet_diagnostic.S2259.severity = none + +# S2445: Blocks should be synchronized on read-only fields +# https://rules.sonarsource.com/csharp/RSPEC-2445 +# +# This is a (partial) duplicate of MA0064. +dotnet_diagnostic.S2445.severity = none + +# S2551: Shared resources should not be used for locking +# https://rules.sonarsource.com/csharp/RSPEC-2551 +# +# This is a duplicate of CA2002, and partial duplicate of MA0064. +dotnet_diagnostic.S2551.severity = none + +# S2583: Conditionally executed code should be reachable +# https://rules.sonarsource.com/csharp/RSPEC-2583 +# +# This rule produces false errors in, for example, for loops. +#dotnet_diagnostic.S2583.severity = none + +# S2699: Tests should include assertions +# https://rules.sonarsource.com/csharp/RSPEC-2699 +# +# Sometimes you want a test in which you invoke a method and just want to verify that it does not throw. +# For example: +# [TestMethod] +# public void InvokeDisposeWithoutNotifyObjectShouldNotThrow() +# { +# _timer.Dispose(); +# } +dotnet_diagnostic.S2699.severity = none + +# S2933: Fields that are only assigned in the constructor should be "readonly" +# https://rules.sonarsource.com/csharp/RSPEC-2933 +# +# This is a duplicate of IDE0044, but IDE0044 is not reported when targeting .NET Framework 4.8. +dotnet_diagnostic.S2933.severity = none + +# S2971: "IEnumerable" LINQs should be simplified +# https://rules.sonarsource.com/csharp/RSPEC-2971 +# +# This is a duplicate of MA0020. +dotnet_diagnostic.S2971.severity = none + +# S3218: Inner class members should not shadow outer class "static" or type members +# https://rules.sonarsource.com/csharp/RSPEC-3218 +# +# This is rather harmless. +dotnet_diagnostic.S3218.severity = none + +# S3267: Loops should be simplified with "LINQ" expressions +# https://rules.sonarsource.com/csharp/RSPEC-3267 +# +# LINQ is the root of all evil :p +dotnet_diagnostic.S3267.severity = none + +# S3376: Attribute, EventArgs, and Exception type names should end with the type being extended +# https://rules.sonarsource.com/csharp/RSPEC-3376 +# +# This is a partial duplicate of MA0058. If we enable the Sonar in all repositories, we should +# consider enabling S3376 in favor of MA0058. +dotnet_diagnostic.S3376.severity = none + +# S3871: Exception types should be "public" +# https://rules.sonarsource.com/csharp/RSPEC-3871 +# +# This is a duplicate of CA1064. +dotnet_diagnostic.S3871.severity = none + +# S3925: "ISerializable" should be implemented correctly +# https://rules.sonarsource.com/csharp/RSPEC-3925 +# +# This is a duplicate of CA2229. +dotnet_diagnostic.S3925.severity = none + +# S3928: Parameter names used into ArgumentException constructors should match an existing one +# https://rules.sonarsource.com/csharp/RSPEC-3928 +# +# This is a duplicate of MA0015. +dotnet_diagnostic.S3928.severity = none + +# S3998: Threads should not lock on objects with weak identity +# https://rules.sonarsource.com/csharp/RSPEC-3998 +# +# This is a duplicate of CA2002, and partial duplicate of MA0064. +dotnet_diagnostic.S3998.severity = none + +# S4456: Parameter validation in yielding methods should be wrapped +# https://rules.sonarsource.com/csharp/RSPEC-4456 +# +# This is a duplicate of MA0050. +dotnet_diagnostic.S4456.severity = none + +# S4487: Unread "private" fields should be removed +# https://rules.sonarsource.com/csharp/RSPEC-4487 +# +# This is a duplicate of IDE0052. +dotnet_diagnostic.S4487.severity = none + +# S4581: "new Guid()" should not be used +# https://rules.sonarsource.com/csharp/RSPEC-4581 +# +# This is a partial duplicate of MA0067, and we do not want to report the use of 'default' for a Guid as error. +dotnet_diagnostic.S4581.severity = none + +#### StyleCop rules #### + +# SA1003: Symbols must be spaced correctly +# +# When enabled, a diagnostic is produced when there's a space after a cast. +# For example: +# var x = (int) z; +dotnet_diagnostic.SA1003.severity = none + +# SA1008: Opening parenthesis should not be preceded by a space +# +# When enabled, a diagnostic is produce when a cast precedes braces. +# For example: +# (long) (a * b) +dotnet_diagnostic.SA1008.severity = none + +# SA1009: Closing parenthesis should not be followed by a space +# +# When enabled, a diagnostic is produced when there's a space after a cast. +# For example: +# var x = (int) z; +dotnet_diagnostic.SA1009.severity = none + +# SA1101: Prefix local calls with this +dotnet_diagnostic.SA1101.severity = none + +# SA1116: Split parameters must start on line after declaration +# +# When enabled, a diagnostic is produced when the first parameter is on the same line as the method or constructor. +# For example: +# arrayBuilder.Add(new StatisticsCallInfo(callsByType.Key, +# callsForType.Count); +dotnet_diagnostic.SA1116.severity = none + +# SA1200: Using directives must be placed correctly +# +# This is already verified by the .NET compiler platform analyzers (csharp_using_directive_placement option and IDE0065 rule). +dotnet_diagnostic.SA1200.severity = none + +# SA1201: Elements must appear in the correct order +dotnet_diagnostic.SA1201.severity = none + +# SA1206: Modifiers are not ordered +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1206.md +# +# This is a duplicate of IDE0036, except that it cannot be configured and expects the required modifier to be before the +# accessibility modifier. +dotnet_diagnostic.SA1206.severity = none + +# SA1309: Field names must not begin with underscore +dotnet_diagnostic.SA1309.severity = none + +# SA1405: Debug.Assert should provide message text +# +# To be discussed if we want to enable this. +dotnet_diagnostic.SA1405.severity = none + +# SA1413: Use trailing comma in multi-line initializers +dotnet_diagnostic.SA1413.severity = none + +# SA1503: Braces should not be omitted +# +# This is a duplicate of IDE0011. +dotnet_diagnostic.SA1503.severity = none + +# SA1516: Elements must be separated by blank line +# +# When enabled, a diagnostic is produced for properties with both a get and set accessor. +# For example: +# public bool EnableStatistics +# { +# get +# { +# return _enableStatistics; +# } +# set +# { +# _enableStatistics = value; +# } +# } +dotnet_diagnostic.SA1516.severity = none + +# SA1520: Use braces consistently +# +# Since we always require braces (configured via csharp_prefer_braces and reported as IDE0011), it does not make sense to check if braces +# are used consistently. +dotnet_diagnostic.SA1520.severity = none + +# SA1633: File must have header +# +# We do not use file headers. +dotnet_diagnostic.SA1633.severity = none + +# SA1648: must be used with inheriting class +# +# This rule is disabled by default, hence we need to explicitly enable it. +dotnet_diagnostic.SA1648.severity = error + +# SX1101: Do not prefix local members with 'this.' +# +# This rule is disabled by default, hence we need to explicitly enable it. +dotnet_diagnostic.SX1101.severity = error + +# SX1309: Field names must begin with underscore +# +# This rule is disabled by default, hence we need to explicitly enable it. +dotnet_diagnostic.SX1309.severity = error + +# SX1309S: Static field names must begin with underscore +# +# This rule is disabled by default, hence we need to explicitly enable it. +dotnet_diagnostic.SX1309S.severity = error + +#### Meziantou.Analyzer rules #### + +# MA0002: Use an overload that has a IEqualityComparer or IComparer parameter +# +# In .NET (Core) there have been quite some optimizations for EqualityComparer.Default (eg. https://github.com/dotnet/coreclr/pull/14125) +# and Comparer.Default (eg. https://github.com/dotnet/runtime/pull/48160). +# +# We'll have to verify impact on performance before we decide to use specific comparers (eg. StringComparer.InvariantCultureIgnoreCase). +dotnet_diagnostic.MA0002.severity = none + +# MA0006: Use string.Equals instead of Equals operator +# +# We almost always want ordinal comparison, and using the explicit overload adds a little overhead +# and is more chatty. +dotnet_diagnostic.MA0006.severity = none + +# MA0007: Add a comma after the last value +# +# We do not add a comma after the last value in multi-line initializers. +# For example: +# public enum Sex +# { +# Male = 1, +# Female = 2 // No comma here +# } +# +# Note: +# This is a duplicate of SA1413. +dotnet_diagnostic.MA0007.severity = none + +# MA0009: Add regex evaluation timeout +# +# We do not see a need guard our regex's against a DOS attack. +dotnet_diagnostic.MA0009.severity = none + +# MA0011: IFormatProvider is missing +# +# Also report diagnostic in ToString(...) methods +MA0011.exclude_tostring_methods = false + +# MA0012: Do not raise reserved exception type +# +# This is a duplicate of CA2201. +dotnet_diagnostic.MA0012.severity = none + +# MA0014: Do not raise System.ApplicationException type +# +# This is a duplicate of CA2201. +dotnet_diagnostic.MA0014.severity = none + +# MA0016: Prefer returning collection abstraction instead of implementation +# +# This is a duplicate of CA1002. +dotnet_diagnostic.MA0016.severity = none + +# MA0018: Do not declare static members on generic types +# +# This is a duplicate of CA1000. +dotnet_diagnostic.MA0018.severity = none + +# MA0021: Use StringComparer.GetHashCode instead of string.GetHashCode +# +# No strong need for this, and may negatively affect performance. +dotnet_diagnostic.MA0021.severity = none + +# MA0031: Optimize Enumerable.Count() usage +# https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md +# +# The proposed code is less readable. +# +# For example: +# +# the following code fragment: +# enumerable.Count() > 10; +# +# would become: +# enumerable.Skip(10).Any(); +dotnet_diagnostic.MA0031.severity = none + +# MA0036: Make class static +# +# This is a partial duplicate of CA1052. +dotnet_diagnostic.MA0036.severity = none + +# MA0038: Make method static +# +# This is a partial duplicate of, and deprecated in favor of, CA1822. +dotnet_diagnostic.MA0038.severity = none + +# MA0041: Make property static +# +# This is a partial duplicate of, and deprecated in favor of, CA1822. +dotnet_diagnostic.MA0041.severity = none + +# MA0048: File name must match type name +# +# This is a duplicate of SA1649. +dotnet_diagnostic.MA0048.severity = none + +# MA0049: Type name should not match containing namespace +# +# This is a duplicate of CA1724 +dotnet_diagnostic.MA0049.severity = none + +# MA0051: Method is too long +# +# We do not want to limit the number of lines or statements per method. +dotnet_diagnostic.MA0051.severity = none + +# MA0053: Make class sealed +# +# Also report diagnostic for public types. +MA0053.public_class_should_be_sealed = true + +# MA0053: Make class sealed +# +# Also report diagnostic for types that derive from System.Exception. +MA0053.exceptions_should_be_sealed = true + +# MA0053: Make class sealed +# +# Also report diagnostic for types that define (new) virtual members. +MA0053.class_with_virtual_member_shoud_be_sealed = true + +# MA0112: Use 'Count > 0' instead of 'Any()' +# +# This rule is disabled by default, hence we need to explicitly enable it. +dotnet_diagnostic.MA0112.severity = error + +#### .NET Compiler Platform code quality rules #### + +# CA1002: Do not expose generic lists +# +# For performance reasons - to avoid interface dispatch - we expose generic lists +# instead of a base class or interface. +dotnet_diagnostic.CA1002.severity = none + +# CA1008: Enums should have zero value +# +# TODO: To be discussed. Having a zero value offers a performance advantage. +dotnet_diagnostic.CA1008.severity = none + +# CA1014: Mark assemblies with CLSCompliantAttribute +# +# This rule is disabled by default, hence we need to explicitly enable it. +# +# Even when enabled, this diagnostic does not appear to be reported for assemblies without CLSCompliantAttribute. +# We reported this issue as https://github.com/dotnet/roslyn-analyzers/issues/6563. +dotnet_diagnostic.CA1014.severity = error + +# CA1051: Do not declare visible instance fields +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1051 +# +# This is a duplicate of S1104 and SA1401. +dotnet_diagnostic.CA1051.severity = none + +# CA1052: Static holder types should be Static or NotInheritable +# +# By default, this diagnostic is only reported for public types. +dotnet_code_quality.CA1052.api_surface = all + +# CA1303: Do not pass literals as localized parameters +# +# We don't care about localization. +dotnet_diagnostic.CA1303.severity = none + +# CA1305: Specify IFormatProvider +# +# This is a an equivalent of MA0011, except that it does not report a diagnostic for the use of +# DateTime.TryParse(string s, out DateTime result). +# +# Submitted https://github.com/dotnet/roslyn-analyzers/issues/6096 to fix CA1305. +dotnet_diagnostic.CA1305.severity = none + +# CA1510: Use ArgumentNullException throw helper +# +# This is only available in .NET 6.0 and higher. We'd need to use conditional compilation to only +# use these throw helper when targeting a framework that supports it. +dotnet_diagnostic.CA1510.severity = none + +# CA1725: Parameter names should match base declaration +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1725 +# +# This is a duplicate of S927, but contains at least one bug: +# https://github.com/dotnet/roslyn-analyzers/issues/6461 +# +# Since we do not enable any of the Sonar rules by default, we'll leave CA1725 enabled. +dotnet_diagnostic.CA1725.severity = error + +# CA1819: Properties should not return arrays +# +# Arrays offer better performance than collections. +dotnet_diagnostic.CA1819.severity = none + +# CA1828: Mark members as static +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822 +# +# Documentation does not mention which API surface(s) this rule runs on, so we explictly configure it. +dotnet_code_quality.CA1828.api_surface = all + +# CA1852: Seal internal types +# +# Similar to MA0053, but does not support public types and types that define (new) virtual members. +dotnet_diagnostic.CA1852.severity = none + +# CA1859: Change return type for improved performance +# +# By default, this diagnostic is only reported for private members. +dotnet_code_quality.CA1859.api_surface = all + +# CA2208: Instantiate argument exceptions correctly +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2208 +# +# This is similar to, but less powerful than, MA0015. +dotnet_diagnostic.CA2208.severity = none + +#### Roslyn IDE analyser rules #### + +# IDE0032: Use auto-implemented property +# +# For performance reasons, we do not always want to enforce the use of +# auto-implemented properties. +dotnet_diagnostic.IDE0032.severity = suggestion + +# IDE0045: Use conditional expression for assignment +# +# This does not always result in cleaner/clearer code. +dotnet_diagnostic.IDE0045.severity = none + +# IDE0046: Use conditional expression for return +# +# Using a conditional expression is not always a clear win for readability. +# +# Configured using 'dotnet_style_prefer_conditional_expression_over_return' +dotnet_diagnostic.IDE0046.severity = suggestion + +# IDE0055: Fix formatting +# +# When enabled, diagnostics are reported for indented object initializers. +# For example: +# _content = new Person +# { +# Name = "\u13AAlarm" +# }; +# +# There are no settings to configure this correctly, unless https://github.com/dotnet/roslyn/issues/63256 (or similar) is ever implemented. +dotnet_diagnostic.IDE0055.severity = none + +# IDE0270: Null check can be simplified +# +# var inputPath = originalDossierPathList.Find(x => x.id == updatedPath.id); +# if (inputPath is null) +# { +# throw new PcsException($"Path id ({updatedPath.id}) unknown in PCS for dossier id {dossierFromTs.dossier.id}", updatedPath.id); +# } +# +# We do not want to modify the code using a null coalescing operator: +# +# var inputPath = originalDossierPathList.Find(x => x.id == updatedPath.id) ?? throw new PcsException($"Path id ({updatedPath.id}) unknown in PCS for dossier id {dossierFromTs.dossier.id}", updatedPath.id); +dotnet_diagnostic.IDE0270.severity = none + +#### .NET Compiler Platform code style rules #### + +### Language rules ### + +## Modifier preferences + +dotnet_style_require_accessibility_modifiers = true +dotnet_style_readonly_field = true +csharp_prefer_static_local_function = true + +## Parentheses preferences + +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary + +# Expression-level preferences + +dotnet_style_object_initializer = true +csharp_style_inlined_variable_declaration = true +dotnet_style_collection_initializer = true +dotnet_style_prefer_auto_properties = true +dotnet_style_explicit_tuple_names = true +csharp_prefer_simple_default_expression = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_inferred_anonymous_type_member_names = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_deconstructed_variable_declaration = false +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_compound_assignment = true +csharp_style_prefer_index_operator = false +csharp_style_prefer_range_operator = false +dotnet_style_prefer_simplified_interpolation = false +dotnet_style_prefer_simplified_boolean_expressions = true +csharp_style_implicit_object_creation_when_type_is_apparent = false +csharp_style_prefer_tuple_swap = false + +# Namespace declaration preferences + +csharp_style_namespace_declarations = block_scoped + +# Null-checking preferences + +csharp_style_throw_expression = false +dotnet_style_coalesce_expression = true +dotnet_style_null_propagation = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_conditional_delegate_call = true + +# 'var' preferences + +csharp_style_var_for_built_in_types = true +csharp_style_var_when_type_is_apparent = true +csharp_style_var_elsewhere = true + +# Expression-bodies members + +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = false +csharp_style_expression_bodied_indexers = false +csharp_style_expression_bodied_accessors = false +csharp_style_expression_bodied_lambdas = false +csharp_style_expression_bodied_local_functions = false + +# Pattern matching preferences + +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_switch_expression = false +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_extended_property_pattern = true + +# Code block preferences + +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = false + +# Using directive preferences + +csharp_using_directive_placement = outside_namespace + +# Namespace naming preferences + +dotnet_style_namespace_match_folder = true + +# Undocumented preferences + +csharp_style_prefer_method_group_conversion = false +csharp_style_prefer_top_level_statements = false + +### Formatting rules ### + +## .NET formatting options ## + +# Using directive options + +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = true + +## C# formatting options ## + +# New-line options + +# TNIS-13005: Enabling this setting breaks Resharper indentation for lambdas +#csharp_new_line_before_open_brace = accessors, anonymous_methods, anonymous_types, control_blocks, events, indexers, lambdas, local_functions, methods, object_collection_array_initializers, properties, types +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +# Enabling this setting breaks Resharper formatting for an enum field reference that is +# deeply nested in an object initializer. +# +# For an example, see TDataExchangeGeneralEnricher_CernInfrastructureObstruction. +#csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation options + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current +csharp_indent_block_contents = true +# TNIS-13005: Enabling this setting breaks Resharper indentation for lambdas +#csharp_indent_braces = false +# TNIS-13005: Enabling this setting breaks Resharper indentation for lambdas +#csharp_indent_case_contents_when_block = true + +# Spacing options + +csharp_space_after_cast = true +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false + +# Wrap options + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +### Naming styles ### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.private_fields_camel_case_begins_with_underscore.symbols = private_fields +dotnet_naming_rule.private_fields_camel_case_begins_with_underscore.style = camel_case_begins_with_underscore +dotnet_naming_rule.private_fields_camel_case_begins_with_underscore.severity = error + +dotnet_naming_rule.private_static_fields_camel_case_begins_with_underscore.symbols = private_static_fields +dotnet_naming_rule.private_static_fields_camel_case_begins_with_underscore.style = camel_case_begins_with_underscore +dotnet_naming_rule.private_static_fields_camel_case_begins_with_underscore.severity = error + +dotnet_naming_rule.private_static_readonly_fields_pascal_case.symbols = private_static_readonly_fields +dotnet_naming_rule.private_static_readonly_fields_pascal_case.style = pascal_case +dotnet_naming_rule.private_static_readonly_fields_pascal_case.severity = error + +dotnet_naming_rule.private_const_fields_pascal_case.symbols = private_const_fields +dotnet_naming_rule.private_const_fields_pascal_case.style = pascal_case +dotnet_naming_rule.private_const_fields_pascal_case.severity = error + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = * +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = * +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = * +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_fields.required_modifiers = + +dotnet_naming_symbols.private_static_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_static_fields.required_modifiers = static + +dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = static, readonly + +dotnet_naming_symbols.private_const_fields.applicable_kinds = field +dotnet_naming_symbols.private_const_fields.applicable_accessibilities = private +dotnet_naming_symbols.private_const_fields.required_modifiers = const + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.camel_case_begins_with_underscore.required_prefix = _ +dotnet_naming_style.camel_case_begins_with_underscore.required_suffix = +dotnet_naming_style.camel_case_begins_with_underscore.word_separator = +dotnet_naming_style.camel_case_begins_with_underscore.capitalization = camel_case + +#### .NET Compiler Platform general options #### + +# Change the default rule severity for all analyzer rules that are enabled by default +dotnet_analyzer_diagnostic.severity = error + +#### .NET Compiler Platform code refactoring rules #### + +dotnet_style_operator_placement_when_wrapping = end_of_line + +#### ReSharper code style for C# #### + +## Blank Lines + +resharper_csharp_blank_lines_around_region = 1 +resharper_csharp_blank_lines_inside_region = 1 +resharper_csharp_blank_lines_before_single_line_comment = 1 +resharper_csharp_keep_blank_lines_in_declarations = 1 +resharper_csharp_remove_blank_lines_near_braces_in_declarations = true +resharper_csharp_blank_lines_after_start_comment = 1 +resharper_csharp_blank_lines_between_using_groups = 1 +resharper_csharp_blank_lines_after_using_list = 1 +resharper_csharp_blank_lines_around_namespace = 1 +resharper_csharp_blank_lines_inside_namespace = 0 +resharper_csharp_blank_lines_after_file_scoped_namespace_directive = 1 +resharper_csharp_blank_lines_around_type = 1 +resharper_csharp_blank_lines_around_single_line_type = 1 +resharper_csharp_blank_lines_inside_type = 0 +resharper_csharp_blank_lines_around_field = 0 +resharper_csharp_blank_lines_around_single_line_field = 0 +resharper_csharp_blank_lines_around_property = 1 +resharper_csharp_blank_lines_around_single_line_property = 1 +resharper_csharp_blank_lines_around_auto_property = 1 +resharper_csharp_blank_lines_around_single_line_auto_property = 1 +resharper_csharp_blank_lines_around_accessor = 0 +resharper_csharp_blank_lines_around_single_line_accessor = 0 +resharper_csharp_blank_lines_around_invocable = 1 +resharper_csharp_blank_lines_around_single_line_invocable = 1 +resharper_csharp_keep_blank_lines_in_code = 1 +resharper_csharp_remove_blank_lines_near_braces_in_code = true +resharper_csharp_blank_lines_around_local_method = 1 +resharper_csharp_blank_lines_around_single_line_local_method = 1 +resharper_csharp_blank_lines_before_control_transfer_statements = 0 +resharper_csharp_blank_lines_after_control_transfer_statements = 0 +resharper_csharp_blank_lines_before_block_statements = 0 +resharper_csharp_blank_lines_after_block_statements = 1 +resharper_csharp_blank_lines_before_multiline_statements = 0 +resharper_csharp_blank_lines_after_multiline_statements = 0 +resharper_csharp_blank_lines_around_block_case_section = 0 +resharper_csharp_blank_lines_around_multiline_case_section = 0 +resharper_csharp_blank_lines_before_case = 0 +resharper_csharp_blank_lines_after_case = 0 + +## Braces Layout + +resharper_csharp_type_declaration_braces = next_line +resharper_csharp_indent_inside_namespace = true +resharper_csharp_invocable_declaration_braces = next_line +resharper_csharp_anonymous_method_declaration_braces = next_line_shifted_2 +resharper_csharp_accessor_owner_declaration_braces = next_line +resharper_csharp_accessor_declaration_braces = next_line +resharper_csharp_case_block_braces = next_line_shifted_2 +resharper_csharp_initializer_braces = next_line_shifted_2 +resharper_csharp_use_continuous_indent_inside_initializer_braces = true +resharper_csharp_other_braces = next_line +resharper_csharp_allow_comment_after_lbrace = false +resharper_csharp_empty_block_style = multiline + +## Syntax Style + +# 'var' usage in declarations + +resharper_csharp_for_built_in_types = use_var +resharper_csharp_for_simple_types = use_var +resharper_csharp_for_other_types = use_var + +# Instance members qualification + +resharper_csharp_instance_members_qualify_members = none +resharper_csharp_instance_members_qualify_declared_in = base_class + +# Static members qualification + +resharper_csharp_static_members_qualify_with = declared_type +resharper_csharp_static_members_qualify_members = none + +# Built-in types + +resharper_csharp_builtin_type_reference_style = use_keyword +resharper_csharp_builtin_type_reference_for_member_access_style = use_keyword + +# Reference qualification and 'using' directives + +resharper_csharp_prefer_qualified_reference = false +resharper_csharp_add_imports_to_deepest_scope = false +resharper_csharp_qualified_using_at_nested_scope = false +resharper_csharp_allow_alias = true +resharper_csharp_can_use_global_alias = true + +# Modifiers + +resharper_csharp_default_private_modifier = explicit +resharper_csharp_default_internal_modifier = explicit +resharper_csharp_modifiers_order = public private protected internal file static extern new virtual abstract sealed override readonly unsafe required volatile async + +# Braces + +resharper_csharp_braces_for_ifelse = required +resharper_csharp_braces_for_for = required +resharper_csharp_braces_for_foreach = required +resharper_csharp_braces_for_while = required +resharper_csharp_braces_for_dowhile = required +resharper_csharp_braces_for_using = required +resharper_csharp_braces_for_lock = required +resharper_csharp_braces_for_fixed = required +resharper_csharp_braces_redundant = false + +# Code body + +resharper_csharp_method_or_operator_body = block_body +resharper_csharp_local_function_body = block_body +resharper_csharp_constructor_or_destructor_body = block_body +resharper_csharp_accessor_owner_body = accessors_with_block_body +resharper_csharp_namespace_body = block_scoped +resharper_csharp_use_heuristics_for_body_style = false + +# Trailing comma + +resharper_csharp_trailing_comma_in_multiline_lists = false +resharper_csharp_trailing_comma_in_singleline_lists = false + +# Object creation + +resharper_csharp_object_creation_when_type_evident = explicitly_typed +resharper_csharp_object_creation_when_type_not_evident = explicitly_typed + +# Default value + +resharper_csharp_default_value_when_type_evident = default_literal +resharper_csharp_default_value_when_type_not_evident = default_literal + +## Tabs, Indents, Alignment + +# Nested statements + +resharper_csharp_indent_nested_usings_stmt = false +resharper_csharp_indent_nested_fixed_stmt = false +resharper_csharp_indent_nested_lock_stmt = false +resharper_csharp_indent_nested_for_stmt = true +resharper_csharp_indent_nested_foreach_stmt = true +resharper_csharp_indent_nested_while_stmt = true + +# Parenthesis + +resharper_csharp_use_continuous_indent_inside_parens = true +resharper_csharp_indent_method_decl_pars = outside_and_inside +resharper_csharp_indent_invocation_pars = outside_and_inside +resharper_csharp_indent_statement_pars = outside_and_inside +resharper_csharp_indent_typeparam_angles = outside_and_inside +resharper_csharp_indent_typearg_angles = outside_and_inside +resharper_csharp_indent_pars = outside_and_inside + +# Preprocessor directives + +resharper_csharp_indent_preprocessor_if = no_indent +resharper_csharp_indent_preprocessor_region = usual_indent +resharper_csharp_indent_preprocessor_other = no_indent + +# Other indents + +resharper_indent_switch_labels = true +resharper_csharp_outdent_statement_labels = true +resharper_csharp_indent_type_constraints = true +resharper_csharp_stick_comment = false +resharper_csharp_place_comments_at_first_column = false +resharper_csharp_use_indent_from_previous_element = true +resharper_csharp_indent_braces_inside_statement_conditions = true + +# Align multiline constructs + +resharper_csharp_alignment_tab_fill_style = use_spaces +resharper_csharp_allow_far_alignment = true +resharper_csharp_align_multiline_parameter = true +resharper_csharp_align_multiline_extends_list = true +resharper_csharp_align_linq_query = true +resharper_csharp_align_multiline_binary_expressions_chain = true +resharper_csharp_outdent_binary_ops = false +resharper_csharp_align_multiline_calls_chain = true +resharper_csharp_outdent_dots = false +resharper_csharp_align_multiline_array_and_object_initializer = false +resharper_csharp_align_multiline_switch_expression = false +resharper_csharp_align_multiline_property_pattern = false +resharper_csharp_align_multiline_list_pattern = false +resharper_csharp_align_multiline_binary_patterns = false +resharper_csharp_outdent_binary_pattern_ops = false +resharper_csharp_indent_anonymous_method_block = true +resharper_csharp_align_first_arg_by_paren = false +resharper_csharp_align_multiline_argument = true +resharper_csharp_align_tuple_components = true +resharper_csharp_align_multiline_expression = true +resharper_csharp_align_multiline_statement_conditions = true +resharper_csharp_align_multiline_for_stmt = true +resharper_csharp_align_multiple_declaration = true +resharper_csharp_align_multline_type_parameter_list = true +resharper_csharp_align_multline_type_parameter_constrains = true +resharper_csharp_outdent_commas = false + +## Line Breaks + +# General + +resharper_csharp_keep_user_linebreaks = true +resharper_csharp_max_line_length = 140 +resharper_csharp_wrap_before_comma = false +resharper_csharp_wrap_before_eq = false +resharper_csharp_special_else_if_treatment = true +resharper_csharp_insert_final_newline = true + +# Arrangement of attributes + +resharper_csharp_keep_existing_attribute_arrangement = false +resharper_csharp_place_type_attribute_on_same_line = false +resharper_csharp_place_method_attribute_on_same_line = false +resharper_csharp_place_accessorholder_attribute_on_same_line = false +resharper_csharp_place_accessor_attribute_on_same_line = false +resharper_csharp_place_field_attribute_on_same_line = false +resharper_csharp_place_record_field_attribute_on_same_line = true + +# Arrangement of method signatures + +resharper_csharp_place_constructor_initializer_on_same_line = false +resharper_csharp_place_expr_method_on_single_line = true +resharper_csharp_place_expr_property_on_single_line = true +resharper_csharp_place_expr_accessor_on_single_line = true + +# Arrangement of type parameters, constraints, and base types + +resharper_csharp_place_type_constraints_on_same_line = false +resharper_csharp_wrap_before_first_type_parameter_constraint = true + +# Arrangement of declaration blocks + +resharper_csharp_place_abstract_accessorholder_on_single_line = true + +# Arrangement of statements + +resharper_new_line_before_else = true +resharper_new_line_before_while = true +resharper_new_line_before_catch = true +resharper_new_line_before_finally = true +resharper_wrap_for_stmt_header_style = chop_if_long +resharper_wrap_multiple_declaration_style = chop_always + +## Spaces + +# Preserve existing formatting + +resharper_csharp_extra_spaces = remove_all + +# Before parentheses in statements + +resharper_csharp_space_before_if_parentheses = true +resharper_csharp_space_before_while_parentheses = true +resharper_csharp_space_before_catch_parentheses = true +resharper_csharp_space_before_switch_parentheses = true +resharper_csharp_space_before_for_parentheses = true +resharper_csharp_space_before_foreach_parentheses = true +resharper_csharp_space_before_using_parentheses = true +resharper_csharp_space_before_lock_parentheses = true +resharper_csharp_space_before_fixed_parentheses = true + +# Before other parentheses + +resharper_csharp_space_before_method_call_parentheses = false +resharper_csharp_space_before_empty_method_call_parentheses = false +resharper_csharp_space_before_method_parentheses = false +resharper_csharp_space_before_empty_method_parentheses = false +resharper_csharp_space_before_typeof_parentheses = false +resharper_csharp_space_before_default_parentheses = false +resharper_csharp_space_before_checked_parentheses = false +resharper_csharp_space_before_sizeof_parentheses = false +resharper_csharp_space_before_nameof_parentheses = false +resharper_csharp_space_before_new_parentheses = false +resharper_csharp_space_between_keyword_and_expression = true +resharper_csharp_space_between_keyword_and_type = false + +# Within parentheses in statements + +resharper_csharp_space_within_if_parentheses = false +resharper_csharp_space_within_while_parentheses = false +resharper_csharp_space_within_catch_parentheses = false +resharper_csharp_space_within_switch_parentheses = false +resharper_csharp_space_within_for_parentheses = false +resharper_csharp_space_within_foreach_parentheses = false +resharper_csharp_space_within_using_parentheses = false +resharper_csharp_space_within_lock_parentheses = false +resharper_csharp_space_within_fixed_parentheses = false + +# Within other parentheses + +resharper_csharp_space_within_parentheses = false +resharper_csharp_space_between_typecast_parentheses = false +resharper_csharp_space_between_method_declaration_parameter_list_parentheses = false +resharper_csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +resharper_csharp_space_between_method_call_parameter_list_parentheses = false +resharper_csharp_space_between_method_call_empty_parameter_list_parentheses = false +resharper_csharp_space_within_typeof_parentheses = false +resharper_csharp_space_within_default_parentheses = false +resharper_csharp_space_within_checked_parentheses = false +resharper_csharp_space_within_sizeof_parentheses = false +resharper_csharp_space_within_nameof_parentheses = false +resharper_csharp_space_within_new_parentheses = false + +# Around array brackets + +resharper_csharp_space_before_array_access_brackets = false +resharper_csharp_space_before_open_square_brackets = false +resharper_csharp_space_before_array_rank_brackets = false +resharper_csharp_space_within_array_access_brackets = false +resharper_csharp_space_between_square_brackets = false +resharper_csharp_space_within_array_rank_brackets = false +resharper_csharp_space_within_array_rank_empty_brackets = false +resharper_csharp_space_between_empty_square_bracket = false + +# Around angle brackets + +resharper_csharp_space_before_type_parameter_angle = false +resharper_csharp_space_before_type_argument_angle = false +resharper_csharp_space_within_type_parameter_angles = false +resharper_csharp_space_within_type_argument_angles = false + +### ReSharper code style for XMLDOC ### + +## Tabs and indents + +resharper_xmldoc_indent_style = space +# ReSharper currently ignores this setting. See https://youtrack.jetbrains.com/issue/RSRP-465678/XMLDOC-indent-settings-ignored. +resharper_xmldoc_indent_size = 2 +resharper_xmldoc_tab_width = 2 +resharper_xmldoc_alignment_tab_fill_style = use_spaces +resharper_xmldoc_allow_far_alignment = true + +## Line wrapping + +resharper_xmldoc_max_line_length = 140 +resharper_xmldoc_wrap_tags_and_pi = false + +## Processing instructions + +resharper_xmldoc_spaces_around_eq_in_pi_attribute = false +resharper_xmldoc_space_after_last_pi_attribute = false +resharper_xmldoc_pi_attribute_style = on_single_line +resharper_xmldoc_pi_attributes_indent = align_by_first_attribute +resharper_xmldoc_blank_line_after_pi = false + +## Inside of tag header + +resharper_xmldoc_spaces_around_eq_in_attribute = false +resharper_xmldoc_space_after_last_attribute = false +resharper_xmldoc_space_before_self_closing = false +resharper_xmldoc_attribute_style = do_not_touch +resharper_xmldoc_attribute_indent = align_by_first_attribute + +## Tag content + +resharper_xmldoc_keep_user_linebreaks = true +resharper_xmldoc_linebreaks_inside_tags_for_multiline_elements = true +resharper_xmldoc_linebreaks_inside_tags_for_elements_with_child_elements = false +resharper_xmldoc_spaces_inside_tags = false +resharper_xmldoc_wrap_text = false +resharper_xmldoc_wrap_around_elements = false +# ReSharper currently ignores the 'resharper_xmldoc_indent_size' setting. Once https://youtrack.jetbrains.com/issue/RSRP-465678/XMLDOC-indent-settings-ignored +# is fixed, we should change the value of this setting to 'one_indent'. +resharper_xmldoc_indent_child_elements = zero_indent +resharper_xmldoc_indent_text = zero_indent + +## Around tags + +resharper_xmldoc_max_blank_lines_between_tags = 1 +resharper_xmldoc_linebreak_before_multiline_elements = true +resharper_xmldoc_linebreak_before_singleline_elements = false + +[*.{xml,xsd,csproj,targets,proj,props,runsettings,config}] + +#### ReSharper code style for XML #### + +## Tabs and indents + +resharper_xml_indent_style = space +resharper_xml_indent_size = 4 +resharper_xml_tab_width = 4 +resharper_xml_alignment_tab_fill_style = use_spaces +resharper_xml_allow_far_alignment = true + +## Line wrapping + +resharper_xml_wrap_tags_and_pi = false + +## Processing instructions + +resharper_xml_spaces_around_eq_in_pi_attribute = false +resharper_xml_space_after_last_pi_attribute = false +resharper_xml_pi_attribute_style = on_single_line +resharper_xml_pi_attributes_indent = align_by_first_attribute +resharper_xml_blank_line_after_pi = false + +## Inside of tag header + +resharper_xml_spaces_around_eq_in_attribute = false +resharper_xml_space_after_last_attribute = false +resharper_xml_space_before_self_closing = true +resharper_xml_attribute_style = do_not_touch +resharper_xml_attribute_indent = align_by_first_attribute + +## Tag content + +resharper_xml_keep_user_linebreaks = true +resharper_xml_linebreaks_inside_tags_for_multiline_elements = false +resharper_xml_linebreaks_inside_tags_for_elements_with_child_elements = false +resharper_xml_linebreaks_inside_tags_for_elements_longer_than = false +resharper_xml_spaces_inside_tags = false +resharper_xml_wrap_text = false +resharper_xml_wrap_around_elements = false +resharper_xml_indent_child_elements = one_indent +resharper_xml_indent_text = zero_indent +resharper_xml_max_blank_lines_between_tags = 1 +resharper_xml_linebreak_before_multiline_elements = false +resharper_xml_linebreak_before_singleline_elements = false + +## Other + +resharper_xml_insert_final_newline = true diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..4fd6964ad --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,48 @@ + + + + + + true + $(MSBuildThisFileDirectory)src\Renci.SshNet.snk + true + latest + + false + + + + + false + preview-All + true + + + + + + + + + + + + + diff --git a/src/Renci.SshNet.Tests/Classes/Common/ObjectIdentifierTest.cs b/src/Renci.SshNet.Tests/Classes/Common/ObjectIdentifierTest.cs index 5bfbfc29a..608159424 100644 --- a/src/Renci.SshNet.Tests/Classes/Common/ObjectIdentifierTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Common/ObjectIdentifierTest.cs @@ -1,26 +1,37 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +using Microsoft.VisualStudio.TestTools.UnitTesting; using Renci.SshNet.Common; using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Common -{ - /// - ///This is a test class for ObjectIdentifierTest and is intended - ///to contain all ObjectIdentifierTest Unit Tests - /// +{ [TestClass] - [Ignore] // placeholder for actual test public class ObjectIdentifierTest : TestBase { - /// - ///A test for ObjectIdentifier Constructor - /// [TestMethod] - public void ObjectIdentifierConstructorTest() + public void Constructor_IdentifiersIsNull() { - ulong[] identifiers = null; // TODO: Initialize to an appropriate value - ObjectIdentifier target = new ObjectIdentifier(identifiers); - Assert.Inconclusive("TODO: Implement code to verify target"); + const ulong[] identifiers = null; + + var actualException = Assert.ThrowsException(() => new ObjectIdentifier(identifiers)); + + Assert.AreEqual(typeof(ArgumentNullException), actualException.GetType()); + Assert.IsNull(actualException.InnerException); + Assert.AreEqual(nameof(identifiers), actualException.ParamName); + } + + [TestMethod] + public void Constructor_LengthOfIdentifiersIsLessThanTwo() + { + var identifiers = new[] { 5UL }; + + var actualException = Assert.ThrowsException(() => new ObjectIdentifier(identifiers)); + + Assert.AreEqual(typeof(ArgumentException), actualException.GetType()); + Assert.IsNull(actualException.InnerException); + ArgumentExceptionAssert.MessageEquals("Must contain at least two elements.", actualException); + Assert.AreEqual(nameof(identifiers), actualException.ParamName); } } } diff --git a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs index fea7a6648..43aa9a3b1 100644 --- a/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs +++ b/src/Renci.SshNet.Tests/Classes/Connection/ProtocolVersionExchangeTest_ConnectionClosedByServer_NoDataSentByServer.cs @@ -1,13 +1,15 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Renci.SshNet.Common; -using Renci.SshNet.Connection; -using Renci.SshNet.Tests.Common; -using System; +using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Renci.SshNet.Common; +using Renci.SshNet.Connection; +using Renci.SshNet.Tests.Common; + namespace Renci.SshNet.Tests.Classes.Connection { [TestClass] diff --git a/src/Renci.SshNet.Tests/Classes/MessageEventArgsTest.cs b/src/Renci.SshNet.Tests/Classes/MessageEventArgsTest.cs index 387b5b29e..051fd6c34 100644 --- a/src/Renci.SshNet.Tests/Classes/MessageEventArgsTest.cs +++ b/src/Renci.SshNet.Tests/Classes/MessageEventArgsTest.cs @@ -6,7 +6,6 @@ namespace Renci.SshNet.Tests.Classes /// /// Provides data for message events. /// - /// Message type [TestClass] public class MessageEventArgsTest : TestBase { diff --git a/src/Renci.SshNet.Tests/Classes/Security/Cryptography/HMacTest.cs b/src/Renci.SshNet.Tests/Classes/Security/Cryptography/HMacTest.cs index 13d8f1dda..94e558b2a 100644 --- a/src/Renci.SshNet.Tests/Classes/Security/Cryptography/HMacTest.cs +++ b/src/Renci.SshNet.Tests/Classes/Security/Cryptography/HMacTest.cs @@ -8,7 +8,6 @@ namespace Renci.SshNet.Tests.Classes.Security.Cryptography /// /// Provides HMAC algorithm implementation. /// - /// [TestClass] public class HMacTest : TestBase { diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpStatVfsResponseBuilder.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpStatVfsResponseBuilder.cs index 1331160b1..6dc110f74 100644 --- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpStatVfsResponseBuilder.cs +++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpStatVfsResponseBuilder.cs @@ -147,17 +147,17 @@ protected override void LoadData() base.LoadData(); Information = new SftpFileSytemInformation(ReadUInt64(), // FileSystemBlockSize - ReadUInt64(), // BlockSize - ReadUInt64(), // TotalBlocks - ReadUInt64(), // FreeBlocks - ReadUInt64(), // AvailableBlocks - ReadUInt64(), // TotalNodes - ReadUInt64(), // FreeNodes - ReadUInt64(), // AvailableNodes - ReadUInt64(), // Sid - ReadUInt64(), // Flags - ReadUInt64() // MaxNameLenght - ); + ReadUInt64(), // BlockSize + ReadUInt64(), // TotalBlocks + ReadUInt64(), // FreeBlocks + ReadUInt64(), // AvailableBlocks + ReadUInt64(), // TotalNodes + ReadUInt64(), // FreeNodes + ReadUInt64(), // AvailableNodes + ReadUInt64(), // Sid + ReadUInt64(), // Flags + ReadUInt64() // MaxNameLenght + ); } protected override void SaveData() diff --git a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs index 78319f76f..6815d1609 100644 --- a/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs +++ b/src/Renci.SshNet.Tests/Common/AsyncSocketListener.cs @@ -40,7 +40,7 @@ public AsyncSocketListener(IPEndPoint endPoint) /// /// to invoke on the that is used /// to handle the communication with the remote host, when the remote host has closed the connection; otherwise, - /// . The default is . + /// . The default is . /// public bool ShutdownRemoteCommunicationSocket { get; set; } diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index 80c36aa70..89a270445 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -1,9 +1,16 @@  - 7.3 - true - ..\Renci.SshNet.snk - net462;net6.0;net7.0 + net462;net6.0;net7.0 + + $(NoWarn);CS1591 diff --git a/src/Renci.SshNet.sln b/src/Renci.SshNet.sln index bc1f6f6d3..09953551d 100644 --- a/src/Renci.SshNet.sln +++ b/src/Renci.SshNet.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29521.150 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33326.253 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D}" ProjectSection(SolutionItems) = preProject @@ -23,6 +23,25 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet", "Renci.SshNe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Renci.SshNet.Tests", "Renci.SshNet.Tests\Renci.SshNet.Tests.csproj", "{C45379B9-17B1-4E89-BC2E-6D41726413E8}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{04E8CC26-116E-4116-9558-7ED542548E70}" + ProjectSection(SolutionItems) = preProject + ..\.editorconfig = ..\.editorconfig + ..\.gitattributes = ..\.gitattributes + ..\.gitignore = ..\.gitignore + ..\appveyor.yml = ..\appveyor.yml + ..\CODEOWNERS = ..\CODEOWNERS + ..\Directory.Build.props = ..\Directory.Build.props + ..\LICENSE = ..\LICENSE + ..\README.md = ..\README.md + ..\THIRD-PARTY-NOTICES.TXT = ..\THIRD-PARTY-NOTICES.TXT + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{D21A4D03-0AC2-4613-BB6D-74D2D16A72CC}" + ProjectSection(SolutionItems) = preProject + ..\test\.editorconfig = ..\test\.editorconfig + ..\test\Directory.Build.props = ..\test\Directory.Build.props + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -72,6 +91,7 @@ Global GlobalSection(NestedProjects) = preSolution {94EE3919-19FA-4D9B-8DA9-249050B15232} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} {A6C3FFD3-16A5-44D3-8C1F-3613D6DD17D1} = {2D6CAE62-D053-476F-9BDD-2B1F27FA9C5D} + {D21A4D03-0AC2-4613-BB6D-74D2D16A72CC} = {04E8CC26-116E-4116-9558-7ED542548E70} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BAD6019D-4AF7-4E15-99A0-8036E16FC0E5} diff --git a/src/Renci.SshNet/.editorconfig b/src/Renci.SshNet/.editorconfig new file mode 100644 index 000000000..7c507c75c --- /dev/null +++ b/src/Renci.SshNet/.editorconfig @@ -0,0 +1,25 @@ +[*.cs] + +### StyleCop Analyzers rules ### + +# SA1202: Elements must be ordered by access +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md +dotnet_diagnostic.SA1202.severity = none + +#### .NET Compiler Platform analysers rules #### + +# CA1031: Do not catch general exception types +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1031 +dotnet_diagnostic.CA1031.severity = none + +# CA2213: Disposable fields should be disposed +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2213 +dotnet_diagnostic.CA2213.severity = none + +# IDE0004: Types that own disposable fields should be disposable +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0004 +dotnet_diagnostic.IDE0004.severity = none + +# IDE0048: Add parentheses for clarity +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0047 +dotnet_diagnostic.IDE0048.severity = none diff --git a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs index 2c7d38b0c..d46411044 100644 --- a/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/CryptoAbstraction.cs @@ -8,7 +8,7 @@ internal static class CryptoAbstraction private static readonly System.Security.Cryptography.RandomNumberGenerator Randomizer = CreateRandomNumberGenerator(); /// - /// Generates a array of the specified length, and fills it with a + /// Generates a array of the specified length, and fills it with a /// cryptographically strong random sequence of values. /// /// The length of the array generate. diff --git a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs index e7740d574..3c6fb90a3 100644 --- a/src/Renci.SshNet/Abstractions/SocketAbstraction.cs +++ b/src/Renci.SshNet/Abstractions/SocketAbstraction.cs @@ -20,7 +20,6 @@ public static bool CanRead(Socket socket) } return false; - } /// @@ -80,8 +79,10 @@ private static void ConnectCore(Socket socket, IPEndPoint remoteEndpoint, TimeSp // dispose Socket socket.Dispose(); } + // dispose ManualResetEvent connectCompleted.Dispose(); + // dispose SocketAsyncEventArgs args.Dispose(); @@ -151,8 +152,12 @@ public static int ReadPartial(Socket socket, byte[] buffer, int offset, int size catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.TimedOut) + { throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture, - "Socket read operation has timed out after {0:F0} milliseconds.", timeout.TotalMilliseconds)); + "Socket read operation has timed out after {0:F0} milliseconds.", + timeout.TotalMilliseconds)); + } + throw; } } @@ -168,14 +173,18 @@ public static void ReadContinuous(Socket socket, byte[] buffer, int offset, int { var bytesRead = socket.Receive(buffer, offset, size, SocketFlags.None); if (bytesRead == 0) + { break; + } processReceivedBytesAction(buffer, offset, bytesRead); } catch (SocketException ex) { if (IsErrorResumable(ex.SocketErrorCode)) + { continue; + } switch (ex.SocketErrorCode) { @@ -208,7 +217,9 @@ public static int ReadByte(Socket socket, TimeSpan timeout) { var buffer = new byte[1]; if (Read(socket, buffer, 0, 1, timeout) == 0) + { return -1; + } return buffer[0]; } @@ -221,14 +232,14 @@ public static int ReadByte(Socket socket, TimeSpan timeout) /// The write failed. public static void SendByte(Socket socket, byte value) { - var buffer = new[] {value}; + var buffer = new[] { value }; Send(socket, buffer, 0, 1); } /// /// Receives data from a bound . /// - /// + /// The to read from. /// The number of bytes to receive. /// Specifies the amount of time after which the call will time out. /// @@ -244,7 +255,7 @@ public static void SendByte(Socket socket, byte value) public static byte[] Read(Socket socket, int size, TimeSpan timeout) { var buffer = new byte[size]; - Read(socket, buffer, 0, size, timeout); + _ = Read(socket, buffer, 0, size, timeout); return buffer; } @@ -256,7 +267,7 @@ public static Task ReadAsync(Socket socket, byte[] buffer, int offset, int /// /// Receives data from a bound into a receive buffer. /// - /// + /// The to read from. /// An array of type that is the storage location for the received data. /// The position in parameter to store the received data. /// The number of bytes to receive. @@ -288,7 +299,9 @@ public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeS { var bytesRead = socket.Receive(buffer, offset + totalBytesRead, totalBytesToRead - totalBytesRead, SocketFlags.None); if (bytesRead == 0) + { return 0; + } totalBytesRead += bytesRead; } @@ -301,8 +314,11 @@ public static int Read(Socket socket, byte[] buffer, int offset, int size, TimeS } if (ex.SocketErrorCode == SocketError.TimedOut) + { throw new SshOperationTimeoutException(string.Format(CultureInfo.InvariantCulture, - "Socket read operation has timed out after {0:F0} milliseconds.", readTimeout.TotalMilliseconds)); + "Socket read operation has timed out after {0:F0} milliseconds.", + readTimeout.TotalMilliseconds)); + } throw; } @@ -328,8 +344,10 @@ public static void Send(Socket socket, byte[] data, int offset, int size) { var bytesSent = socket.Send(data, offset + totalBytesSent, totalBytesToSend - totalBytesSent, SocketFlags.None); if (bytesSent == 0) + { throw new SshConnectionException("An established connection was aborted by the server.", DisconnectReason.ConnectionLost); + } totalBytesSent += bytesSent; } @@ -341,9 +359,12 @@ public static void Send(Socket socket, byte[] data, int offset, int size) ThreadAbstraction.Sleep(30); } else - throw; // any serious error occurr + { + throw; // any serious error occurr + } } - } while (totalBytesSent < totalBytesToSend); + } + while (totalBytesSent < totalBytesToSend); } public static bool IsErrorResumable(SocketError socketError) @@ -363,10 +384,8 @@ public static bool IsErrorResumable(SocketError socketError) private static void ConnectCompleted(object sender, SocketAsyncEventArgs e) { var eventWaitHandle = (ManualResetEvent) e.UserToken; - if (eventWaitHandle != null) - eventWaitHandle.Set(); + _ = eventWaitHandle?.Set(); } #endif // FEATURE_SOCKET_EAP - } } diff --git a/src/Renci.SshNet/Abstractions/SocketExtensions.cs b/src/Renci.SshNet/Abstractions/SocketExtensions.cs index 7d3c30f93..84c2f03df 100644 --- a/src/Renci.SshNet/Abstractions/SocketExtensions.cs +++ b/src/Renci.SshNet/Abstractions/SocketExtensions.cs @@ -8,15 +8,14 @@ namespace Renci.SshNet.Abstractions { // Async helpers based on https://devblogs.microsoft.com/pfxteam/awaiting-socket-operations/ - internal static class SocketExtensions { - sealed class SocketAsyncEventArgsAwaitable : SocketAsyncEventArgs, INotifyCompletion + private sealed class SocketAsyncEventArgsAwaitable : SocketAsyncEventArgs, INotifyCompletion { - private readonly static Action SENTINEL = () => { }; + private static readonly Action SENTINEL = () => { }; - private bool isCancelled; - private Action continuationAction; + private bool _isCancelled; + private Action _continuationAction; public SocketAsyncEventArgsAwaitable() { @@ -35,7 +34,8 @@ public SocketAsyncEventArgsAwaitable ExecuteAsync(Func @@ -29,9 +31,11 @@ public static void ExecuteThreadLongRunning(Action action) public static void ExecuteThread(Action action) { if (action == null) - throw new ArgumentNullException("action"); + { + throw new ArgumentNullException(nameof(action)); + } - System.Threading.ThreadPool.QueueUserWorkItem(o => action()); + _ = System.Threading.ThreadPool.QueueUserWorkItem(o => action()); } } } diff --git a/src/Renci.SshNet/AuthenticationMethod.cs b/src/Renci.SshNet/AuthenticationMethod.cs index 1a285d8c8..51e49b7ad 100644 --- a/src/Renci.SshNet/AuthenticationMethod.cs +++ b/src/Renci.SshNet/AuthenticationMethod.cs @@ -1,10 +1,11 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet { /// - /// Base class for all supported authentication methods + /// Base class for all supported authentication methods. /// public abstract class AuthenticationMethod : IAuthenticationMethod { @@ -22,7 +23,7 @@ public abstract class AuthenticationMethod : IAuthenticationMethod public string Username { get; private set; } /// - /// Gets list of allowed authentications. + /// Gets or sets the list of allowed authentications. /// public string[] AllowedAuthentications { get; protected set; } @@ -34,7 +35,9 @@ public abstract class AuthenticationMethod : IAuthenticationMethod protected AuthenticationMethod(string username) { if (username.IsNullOrWhiteSpace()) + { throw new ArgumentException("username"); + } Username = username; } diff --git a/src/Renci.SshNet/BaseClient.cs b/src/Renci.SshNet/BaseClient.cs index fdc4e3a39..6596ceedb 100644 --- a/src/Renci.SshNet/BaseClient.cs +++ b/src/Renci.SshNet/BaseClient.cs @@ -24,6 +24,7 @@ public abstract class BaseClient : IBaseClient, IDisposable private TimeSpan _keepAliveInterval; private Timer _keepAliveTimer; private ConnectionInfo _connectionInfo; + private bool _isDisposed; /// /// Gets the current session. @@ -101,7 +102,9 @@ public TimeSpan KeepAliveInterval CheckDisposed(); if (value == _keepAliveInterval) + { return; + } if (value == SshNet.Session.InfiniteTimeSpan) { @@ -114,8 +117,7 @@ public TimeSpan KeepAliveInterval { // change the due time and interval of the timer if has already // been created (which means the client is connected) - - _keepAliveTimer.Change(value, value); + _ = _keepAliveTimer.Change(value, value); } else if (IsSessionConnected()) { @@ -127,9 +129,10 @@ public TimeSpan KeepAliveInterval _keepAliveTimer = CreateKeepAliveTimer(value, value); } - // note that if the client is not yet connected, then the timer will be created with the + // note that if the client is not yet connected, then the timer will be created with the // new interval when Connect() is invoked } + _keepAliveInterval = value; } } @@ -180,9 +183,14 @@ protected BaseClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo) internal BaseClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory) { if (connectionInfo == null) - throw new ArgumentNullException("connectionInfo"); + { + throw new ArgumentNullException(nameof(connectionInfo)); + } + if (serviceFactory == null) - throw new ArgumentNullException("serviceFactory"); + { + throw new ArgumentNullException(nameof(serviceFactory)); + } ConnectionInfo = connectionInfo; _ownsConnectionInfo = ownsConnectionInfo; @@ -205,26 +213,29 @@ public void Connect() // TODO (see issue #1758): // we're not stopping the keep-alive timer and disposing the session here - // + // // we could do this but there would still be side effects as concrete // implementations may still hang on to the original session - // + // // therefore it would be better to actually invoke the Disconnect method // (and then the Dispose on the session) but even that would have side effects // eg. it would remove all forwarded ports from SshClient - // + // // I think we should modify our concrete clients to better deal with a - // disconnect. In case of SshClient this would mean not removing the + // disconnect. In case of SshClient this would mean not removing the // forwarded ports on disconnect (but only on dispose ?) and link a // forwarded port with a client instead of with a session // // To be discussed with Oleg (or whoever is interested) if (IsSessionConnected()) + { throw new InvalidOperationException("The client is already connected."); + } OnConnecting(); Session = CreateAndConnectSession(); + try { // Even though the method we invoke makes you believe otherwise, at this point only @@ -238,6 +249,7 @@ public void Connect() DisposeSession(); throw; } + StartKeepAliveTimer(); } @@ -260,26 +272,29 @@ public async Task ConnectAsync(CancellationToken cancellationToken) // TODO (see issue #1758): // we're not stopping the keep-alive timer and disposing the session here - // + // // we could do this but there would still be side effects as concrete // implementations may still hang on to the original session - // + // // therefore it would be better to actually invoke the Disconnect method // (and then the Dispose on the session) but even that would have side effects // eg. it would remove all forwarded ports from SshClient - // + // // I think we should modify our concrete clients to better deal with a - // disconnect. In case of SshClient this would mean not removing the + // disconnect. In case of SshClient this would mean not removing the // forwarded ports on disconnect (but only on dispose ?) and link a // forwarded port with a client instead of with a session // // To be discussed with Oleg (or whoever is interested) if (IsSessionConnected()) + { throw new InvalidOperationException("The client is already connected."); + } OnConnecting(); Session = await CreateAndConnectSessionAsync(cancellationToken).ConfigureAwait(false); + try { // Even though the method we invoke makes you believe otherwise, at this point only @@ -293,6 +308,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken) DisposeSession(); throw; } + StartKeepAliveTimer(); } @@ -352,11 +368,7 @@ protected virtual void OnConnected() /// protected virtual void OnDisconnecting() { - var session = Session; - if (session != null) - { - session.OnDisconnecting(); - } + Session?.OnDisconnecting(); } /// @@ -368,26 +380,14 @@ protected virtual void OnDisconnected() private void Session_ErrorOccured(object sender, ExceptionEventArgs e) { - var handler = ErrorOccurred; - if (handler != null) - { - handler(this, e); - } + ErrorOccurred?.Invoke(this, e); } private void Session_HostKeyReceived(object sender, HostKeyEventArgs e) { - var handler = HostKeyReceived; - if (handler != null) - { - handler(this, e); - } + HostKeyReceived?.Invoke(this, e); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// @@ -395,18 +395,20 @@ public void Dispose() { DiagnosticAbstraction.Log("Disposing client."); - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -414,9 +416,10 @@ protected virtual void Dispose(bool disposing) if (_ownsConnectionInfo && _connectionInfo != null) { - var connectionInfoDisposable = _connectionInfo as IDisposable; - if (connectionInfoDisposable != null) + if (_connectionInfo is IDisposable connectionInfoDisposable) + { connectionInfoDisposable.Dispose(); + } _connectionInfo = null; } @@ -431,20 +434,19 @@ protected virtual void Dispose(bool disposing) protected void CheckDisposed() { if (_isDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~BaseClient() { - Dispose(false); + Dispose(disposing: false); } - #endregion - /// /// Stops the keep-alive timer, and waits until all timer callbacks have been /// executed. @@ -452,7 +454,9 @@ protected void CheckDisposed() private void StopKeepAliveTimer() { if (_keepAliveTimer == null) + { return; + } _keepAliveTimer.Dispose(); _keepAliveTimer = null; @@ -464,14 +468,16 @@ private void SendKeepAliveMessage() // do nothing if we have disposed or disconnected if (session == null) + { return; + } // do not send multiple keep-alive messages concurrently if (Monitor.TryEnter(_keepAliveLock)) { try { - session.TrySendMessage(new IgnoreMessage()); + _ = session.TrySendMessage(new IgnoreMessage()); } finally { @@ -490,11 +496,15 @@ private void SendKeepAliveMessage() private void StartKeepAliveTimer() { if (_keepAliveInterval == SshNet.Session.InfiniteTimeSpan) + { return; + } if (_keepAliveTimer != null) + { // timer is already started return; + } _keepAliveTimer = CreateKeepAliveTimer(_keepAliveInterval, _keepAliveInterval); } diff --git a/src/Renci.SshNet/Channels/Channel.cs b/src/Renci.SshNet/Channels/Channel.cs index a6311a981..df76e67cc 100644 --- a/src/Renci.SshNet/Channels/Channel.cs +++ b/src/Renci.SshNet/Channels/Channel.cs @@ -1,11 +1,12 @@ using System; +using System.Globalization; using System.Net.Sockets; using System.Threading; + +using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Connection; -using System.Globalization; -using Renci.SshNet.Abstractions; namespace Renci.SshNet.Channels { @@ -14,14 +15,15 @@ namespace Renci.SshNet.Channels /// internal abstract class Channel : IChannel { - private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(false); - private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(false); private readonly object _serverWindowSizeLock = new object(); private readonly uint _initialWindowSize; + private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(initialState: false); + private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(initialState: false); private uint? _remoteWindowSize; private uint? _remoteChannelNumber; private uint? _remotePacketSize; private ISession _session; + private bool _isDisposed; /// /// Holds a value indicating whether the SSH_MSG_CHANNEL_CLOSE has been sent to the remote party. @@ -66,7 +68,7 @@ internal abstract class Channel : IChannel public event EventHandler Exception; /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The session. /// The local channel number. @@ -155,7 +157,10 @@ public uint RemoteChannelNumber get { if (!_remoteChannelNumber.HasValue) + { throw CreateRemoteChannelInfoNotAvailableException(); + } + return _remoteChannelNumber.Value; } private set @@ -177,7 +182,10 @@ public uint RemotePacketSize get { if (!_remotePacketSize.HasValue) + { throw CreateRemoteChannelInfoNotAvailableException(); + } + return _remotePacketSize.Value; } private set @@ -197,7 +205,10 @@ public uint RemoteWindowSize get { if (!_remoteWindowSize.HasValue) + { throw CreateRemoteChannelInfoNotAvailableException(); + } + return _remoteWindowSize.Value; } private set @@ -207,15 +218,13 @@ private set } /// - /// Gets a value indicating whether this channel is open. + /// Gets or sets a value indicating whether this channel is open. /// /// /// true if this channel is open; otherwise, false. /// public bool IsOpen { get; protected set; } - #region Message events - /// /// Occurs when is received. /// @@ -251,8 +260,6 @@ private set /// public event EventHandler RequestFailed; - #endregion - /// /// Gets a value indicating whether the session is connected. /// @@ -282,6 +289,12 @@ protected SemaphoreLight SessionSemaphore get { return _session.SessionSemaphore; } } + /// + /// Initializes the information on the remote channel. + /// + /// The remote channel number. + /// The remote window size. + /// The remote packet size. protected void InitializeRemoteInfo(uint remoteChannelNumber, uint remoteWindowSize, uint remotePacketSize) { RemoteChannelNumber = remoteChannelNumber; @@ -320,7 +333,9 @@ public void SendData(byte[] data, int offset, int size) { // send channel messages only while channel is open if (!IsOpen) + { return; + } var totalBytesToSend = size; while (totalBytesToSend > 0) @@ -338,8 +353,6 @@ public void SendData(byte[] data, int offset, int size) } } - #region Channel virtual methods - /// /// Called when channel window need to be adjust. /// @@ -350,7 +363,8 @@ protected virtual void OnWindowAdjust(uint bytesToAdd) { RemoteWindowSize += bytesToAdd; } - _channelServerWindowAdjustWaitHandle.Set(); + + _ = _channelServerWindowAdjustWaitHandle.Set(); } /// @@ -361,9 +375,7 @@ protected virtual void OnData(byte[] data) { AdjustDataWindow(data); - var dataReceived = DataReceived; - if (dataReceived != null) - dataReceived(this, new ChannelDataEventArgs(LocalChannelNumber, data)); + DataReceived?.Invoke(this, new ChannelDataEventArgs(LocalChannelNumber, data)); } /// @@ -375,9 +387,7 @@ protected virtual void OnExtendedData(byte[] data, uint dataTypeCode) { AdjustDataWindow(data); - var extendedDataReceived = ExtendedDataReceived; - if (extendedDataReceived != null) - extendedDataReceived(this, new ChannelExtendedDataEventArgs(LocalChannelNumber, data, dataTypeCode)); + ExtendedDataReceived?.Invoke(this, new ChannelExtendedDataEventArgs(LocalChannelNumber, data, dataTypeCode)); } /// @@ -387,9 +397,7 @@ protected virtual void OnEof() { _eofMessageReceived = true; - var endOfData = EndOfData; - if (endOfData != null) - endOfData(this, new ChannelEventArgs(LocalChannelNumber)); + EndOfData?.Invoke(this, new ChannelEventArgs(LocalChannelNumber)); } /// @@ -404,7 +412,9 @@ protected virtual void OnClose() // be blocked waiting for this signal. var channelClosedWaitHandle = _channelClosedWaitHandle; if (channelClosedWaitHandle != null) - channelClosedWaitHandle.Set(); + { + _ = channelClosedWaitHandle.Set(); + } // close the channel Close(); @@ -416,19 +426,15 @@ protected virtual void OnClose() /// Channel request information. protected virtual void OnRequest(RequestInfo info) { - var requestReceived = RequestReceived; - if (requestReceived != null) - requestReceived(this, new ChannelRequestEventArgs(info)); + RequestReceived?.Invoke(this, new ChannelRequestEventArgs(info)); } /// - /// Called when channel request was successful + /// Called when channel request was successful. /// protected virtual void OnSuccess() { - var requestSuccessed = RequestSucceeded; - if (requestSuccessed != null) - requestSuccessed(this, new ChannelEventArgs(LocalChannelNumber)); + RequestSucceeded?.Invoke(this, new ChannelEventArgs(LocalChannelNumber)); } /// @@ -436,24 +442,16 @@ protected virtual void OnSuccess() /// protected virtual void OnFailure() { - var requestFailed = RequestFailed; - if (requestFailed != null) - requestFailed(this, new ChannelEventArgs(LocalChannelNumber)); + RequestFailed?.Invoke(this, new ChannelEventArgs(LocalChannelNumber)); } - #endregion // Channel virtual methods - /// /// Raises event. /// /// The exception. private void RaiseExceptionEvent(Exception exception) { - var handlers = Exception; - if (handlers != null) - { - handlers(this, new ExceptionEventArgs(exception)); - } + Exception?.Invoke(this, new ExceptionEventArgs(exception)); } /// @@ -479,9 +477,11 @@ private bool TrySendMessage(Message message) /// The message. protected void SendMessage(Message message) { - // send channel messages only while channel is open + // Send channel messages only while channel is open if (!IsOpen) + { return; + } _session.SendMessage(message); } @@ -493,7 +493,9 @@ protected void SendMessage(Message message) public void SendEof() { if (!IsOpen) + { throw CreateChannelClosedException(); + } lock (this) { @@ -516,14 +518,16 @@ protected void WaitOnHandle(WaitHandle waitHandle) /// protected virtual void Close() { - // synchronize sending SSH_MSG_CHANNEL_EOF and SSH_MSG_CHANNEL_CLOSE to ensure that these messages - // are sent in that other; when both the client and the server attempt to close the channel at the - // same time we would otherwise risk sending the SSH_MSG_CHANNEL_EOF after the SSH_MSG_CHANNEL_CLOSE - // message causing the server to disconnect the session. + /* + * Synchronize sending SSH_MSG_CHANNEL_EOF and SSH_MSG_CHANNEL_CLOSE to ensure that these messages + * are sent in that other; when both the client and the server attempt to close the channel at the + * same time we would otherwise risk sending the SSH_MSG_CHANNEL_EOF after the SSH_MSG_CHANNEL_CLOSE + * message causing the server to disconnect the session. + */ lock (this) { - // send EOF message first the following conditions are met: + // Send EOF message first the following conditions are met: // * we have not sent a SSH_MSG_CHANNEL_EOF message // * remote party has not already sent a SSH_MSG_CHANNEL_EOF message // * remote party has not already sent a SSH_MSG_CHANNEL_CLOSE message @@ -565,11 +569,7 @@ protected virtual void Close() if (_closeMessageReceived) { // raise event signaling that both ends of the channel have been closed - var closed = Closed; - if (closed != null) - { - closed(this, new ChannelEventArgs(LocalChannelNumber)); - } + Closed?.Invoke(this, new ChannelEventArgs(LocalChannelNumber)); } } } @@ -623,8 +623,6 @@ private void Session_ErrorOccured(object sender, ExceptionEventArgs e) } } - #region Channel message event handlers - private void OnChannelWindowAdjust(object sender, MessageEventArgs e) { if (e.Message.LocalChannelNumber == LocalChannelNumber) @@ -706,14 +704,13 @@ private void OnChannelRequest(object sender, MessageEventArgs /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { - if (_isDisposed) - return; - - if (disposing) + if (!_isDisposed && disposing) { Close(); @@ -876,14 +866,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~Channel() { - Dispose(false); + Dispose(disposing: false); } - - #endregion // IDisposable Members } } diff --git a/src/Renci.SshNet/Channels/ChannelDirectTcpip.cs b/src/Renci.SshNet/Channels/ChannelDirectTcpip.cs index b6ba7a0ba..374272b29 100644 --- a/src/Renci.SshNet/Channels/ChannelDirectTcpip.cs +++ b/src/Renci.SshNet/Channels/ChannelDirectTcpip.cs @@ -15,13 +15,13 @@ internal class ChannelDirectTcpip : ClientChannel, IChannelDirectTcpip { private readonly object _socketLock = new object(); - private EventWaitHandle _channelOpen = new AutoResetEvent(false); - private EventWaitHandle _channelData = new AutoResetEvent(false); + private EventWaitHandle _channelOpen = new AutoResetEvent(initialState: false); + private EventWaitHandle _channelData = new AutoResetEvent(initialState: false); private IForwardedPort _forwardedPort; private Socket _socket; /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The session. /// The local channel number. @@ -46,9 +46,14 @@ public override ChannelTypes ChannelType public void Open(string remoteHost, uint port, IForwardedPort forwardedPort, Socket socket) { if (IsOpen) + { throw new SshException("Channel is already open."); + } + if (!IsConnected) + { throw new SshException("Session is not connected."); + } _socket = socket; _forwardedPort = forwardedPort; @@ -56,10 +61,13 @@ public void Open(string remoteHost, uint port, IForwardedPort forwardedPort, Soc var ep = (IPEndPoint) socket.RemoteEndPoint; - // open channel - SendMessage(new ChannelOpenMessage(LocalChannelNumber, LocalWindowSize, LocalPacketSize, - new DirectTcpipChannelInfo(remoteHost, port, ep.Address.ToString(), (uint) ep.Port))); - // Wait for channel to open + // Open channel + SendMessage(new ChannelOpenMessage(LocalChannelNumber, + LocalWindowSize, + LocalPacketSize, + new DirectTcpipChannelInfo(remoteHost, port, ep.Address.ToString(), (uint) ep.Port))); + + // Wait for channel to open WaitOnHandle(_channelOpen); } @@ -82,9 +90,11 @@ private void ForwardedPort_Closing(object sender, EventArgs eventArgs) /// public void Bind() { - // Cannot bind if channel is not open + // Cannot bind if channel is not open if (!IsOpen) + { return; + } var buffer = new byte[RemotePacketSize]; @@ -104,12 +114,16 @@ public void Bind() private void CloseSocket() { if (_socket == null) + { return; + } lock (_socketLock) { if (_socket == null) + { return; + } // closing a socket actually disposes the socket, so we can safely dereference // the field to avoid entering the lock again later @@ -125,12 +139,16 @@ private void CloseSocket() private void ShutdownSocket(SocketShutdown how) { if (_socket == null) + { return; + } lock (_socketLock) { if (!_socket.IsConnected()) + { return; + } try { @@ -199,14 +217,14 @@ protected override void OnOpenConfirmation(uint remoteChannelNumber, uint initia { base.OnOpenConfirmation(remoteChannelNumber, initialWindowSize, maximumPacketSize); - _channelOpen.Set(); + _ = _channelOpen.Set(); } protected override void OnOpenFailure(uint reasonCode, string description, string language) { base.OnOpenFailure(reasonCode, description, language); - _channelOpen.Set(); + _ = _channelOpen.Set(); } /// diff --git a/src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs b/src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs index 7d731b9e5..321a00d02 100644 --- a/src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs +++ b/src/Renci.SshNet/Channels/ChannelForwardedTcpip.cs @@ -120,13 +120,17 @@ private void ForwardedPort_Closing(object sender, EventArgs eventArgs) private void ShutdownSocket(SocketShutdown how) { if (_socket == null) + { return; + } lock (_socketShutdownAndCloseLock) { var socket = _socket; if (!socket.IsConnected()) + { return; + } try { @@ -146,7 +150,9 @@ private void ShutdownSocket(SocketShutdown how) private void CloseSocket() { if (_socket == null) + { return; + } lock (_socketShutdownAndCloseLock) { diff --git a/src/Renci.SshNet/Channels/ChannelSession.cs b/src/Renci.SshNet/Channels/ChannelSession.cs index 38e13096b..3b685c426 100644 --- a/src/Renci.SshNet/Channels/ChannelSession.cs +++ b/src/Renci.SshNet/Channels/ChannelSession.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Threading; + using Renci.SshNet.Common; using Renci.SshNet.Messages.Connection; @@ -13,7 +14,7 @@ namespace Renci.SshNet.Channels internal sealed class ChannelSession : ClientChannel, IChannelSession { /// - /// Counts failed channel open attempts + /// Counts failed channel open attempts. /// private int _failedOpenAttempts; @@ -28,16 +29,16 @@ internal sealed class ChannelSession : ClientChannel, IChannelSession private int _sessionSemaphoreObtained; /// - /// Wait handle to signal when response was received to open the channel + /// Wait handle to signal when response was received to open the channel. /// - private EventWaitHandle _channelOpenResponseWaitHandle = new AutoResetEvent(false); + private EventWaitHandle _channelOpenResponseWaitHandle = new AutoResetEvent(initialState: false); - private EventWaitHandle _channelRequestResponse = new ManualResetEvent(false); + private EventWaitHandle _channelRequestResponse = new ManualResetEvent(initialState: false); private bool _channelRequestSucces; /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The session. /// The local channel number. @@ -64,7 +65,7 @@ public override ChannelTypes ChannelType /// public void Open() { - // Try to open channel several times + // Try to open channel several times while (!IsOpen && _failedOpenAttempts < ConnectionInfo.RetryAttempts) { SendChannelOpenMessage(); @@ -81,7 +82,9 @@ public void Open() } if (!IsOpen) + { throw new SshException(string.Format(CultureInfo.CurrentCulture, "Failed to open a channel after {0} attempts.", _failedOpenAttempts)); + } } /// @@ -93,7 +96,8 @@ public void Open() protected override void OnOpenConfirmation(uint remoteChannelNumber, uint initialWindowSize, uint maximumPacketSize) { base.OnOpenConfirmation(remoteChannelNumber, initialWindowSize, maximumPacketSize); - _channelOpenResponseWaitHandle.Set(); + + _ = _channelOpenResponseWaitHandle.Set(); } /// @@ -106,7 +110,7 @@ protected override void OnOpenFailure(uint reasonCode, string description, strin { _failedOpenAttempts++; ReleaseSemaphore(); - _channelOpenResponseWaitHandle.Set(); + _ = _channelOpenResponseWaitHandle.Set(); } protected override void Close() @@ -129,7 +133,7 @@ protected override void Close() /// public bool SendPseudoTerminalRequest(string environmentVariable, uint columns, uint rows, uint width, uint height, IDictionary terminalModeValues) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new PseudoTerminalRequestInfo(environmentVariable, columns, rows, width, height, terminalModeValues))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -147,7 +151,7 @@ public bool SendPseudoTerminalRequest(string environmentVariable, uint columns, /// public bool SendX11ForwardingRequest(bool isSingleConnection, string protocol, byte[] cookie, uint screenNumber) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new X11ForwardingRequestInfo(isSingleConnection, protocol, cookie, screenNumber))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -163,7 +167,7 @@ public bool SendX11ForwardingRequest(bool isSingleConnection, string protocol, b /// public bool SendEnvironmentVariableRequest(string variableName, string variableValue) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new EnvironmentVariableRequestInfo(variableName, variableValue))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -177,7 +181,7 @@ public bool SendEnvironmentVariableRequest(string variableName, string variableV /// public bool SendShellRequest() { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new ShellRequestInfo())); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -192,7 +196,7 @@ public bool SendShellRequest() /// public bool SendExecRequest(string command) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new ExecRequestInfo(command, ConnectionInfo.Encoding))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -207,7 +211,7 @@ public bool SendExecRequest(string command) /// public bool SendBreakRequest(uint breakLength) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new BreakRequestInfo(breakLength))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -222,7 +226,7 @@ public bool SendBreakRequest(uint breakLength) /// public bool SendSubsystemRequest(string subsystem) { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new SubsystemRequestInfo(subsystem))); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -307,7 +311,7 @@ public bool SendExitSignalRequest(string signalName, bool coreDumped, string err /// public bool SendEndOfWriteRequest() { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new EndOfWriteRequestInfo())); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; @@ -321,23 +325,21 @@ public bool SendEndOfWriteRequest() /// public bool SendKeepAliveRequest() { - _channelRequestResponse.Reset(); + _ = _channelRequestResponse.Reset(); SendMessage(new ChannelRequestMessage(RemoteChannelNumber, new KeepAliveRequestInfo())); WaitOnHandle(_channelRequestResponse); return _channelRequestSucces; } /// - /// Called when channel request was successful + /// Called when channel request was successful. /// protected override void OnSuccess() { base.OnSuccess(); - _channelRequestSucces = true; - var channelRequestResponse = _channelRequestResponse; - if (channelRequestResponse != null) - channelRequestResponse.Set(); + _channelRequestSucces = true; + _ = _channelRequestResponse?.Set(); } /// @@ -346,11 +348,9 @@ protected override void OnSuccess() protected override void OnFailure() { base.OnFailure(); - _channelRequestSucces = false; - var channelRequestResponse = _channelRequestResponse; - if (channelRequestResponse != null) - channelRequestResponse.Set(); + _channelRequestSucces = false; + _ = _channelRequestResponse?.Set(); } /// @@ -407,9 +407,9 @@ private void SendChannelOpenMessage() } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// to release both managed and unmanaged resources; to release only unmanaged resources. protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -442,7 +442,9 @@ protected override void Dispose(bool disposing) private void ReleaseSemaphore() { if (Interlocked.CompareExchange(ref _sessionSemaphoreObtained, 0, 1) == 1) - SessionSemaphore.Release(); + { + _ = SessionSemaphore.Release(); + } } } } diff --git a/src/Renci.SshNet/Channels/ClientChannel.cs b/src/Renci.SshNet/Channels/ClientChannel.cs index 844c18660..1ec03c6bc 100644 --- a/src/Renci.SshNet/Channels/ClientChannel.cs +++ b/src/Renci.SshNet/Channels/ClientChannel.cs @@ -7,7 +7,7 @@ namespace Renci.SshNet.Channels internal abstract class ClientChannel : Channel { /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The session. /// The local channel number. @@ -43,9 +43,7 @@ protected virtual void OnOpenConfirmation(uint remoteChannelNumber, uint initial // Channel is consider to be open when confirmation message was received IsOpen = true; - var openConfirmed = OpenConfirmed; - if (openConfirmed != null) - openConfirmed(this, new ChannelOpenConfirmedEventArgs(remoteChannelNumber, initialWindowSize, maximumPacketSize)); + OpenConfirmed?.Invoke(this, new ChannelOpenConfirmedEventArgs(remoteChannelNumber, initialWindowSize, maximumPacketSize)); } /// @@ -68,9 +66,7 @@ protected void SendMessage(ChannelOpenMessage message) /// The language. protected virtual void OnOpenFailure(uint reasonCode, string description, string language) { - var openFailed = OpenFailed; - if (openFailed != null) - openFailed(this, new ChannelOpenFailedEventArgs(LocalChannelNumber, reasonCode, description, language)); + OpenFailed?.Invoke(this, new ChannelOpenFailedEventArgs(LocalChannelNumber, reasonCode, description, language)); } private void OnChannelOpenConfirmation(object sender, MessageEventArgs e) @@ -79,8 +75,9 @@ private void OnChannelOpenConfirmation(object sender, MessageEventArgs - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The session. /// The local channel number. @@ -14,7 +14,13 @@ internal abstract class ServerChannel : Channel /// The remote channel number. /// The window size of the remote party. /// The maximum size of a data packet that we can send to the remote party. - protected ServerChannel(ISession session, uint localChannelNumber, uint localWindowSize, uint localPacketSize, uint remoteChannelNumber, uint remoteWindowSize, uint remotePacketSize) + protected ServerChannel(ISession session, + uint localChannelNumber, + uint localWindowSize, + uint localPacketSize, + uint remoteChannelNumber, + uint remoteWindowSize, + uint remotePacketSize) : base(session, localChannelNumber, localWindowSize, localPacketSize) { InitializeRemoteInfo(remoteChannelNumber, remoteWindowSize, remotePacketSize); @@ -22,10 +28,10 @@ protected ServerChannel(ISession session, uint localChannelNumber, uint localWin protected void SendMessage(ChannelOpenConfirmationMessage message) { - // No need to check whether channel is open when trying to open a channel + // No need to check whether channel is open when trying to open a channel Session.SendMessage(message); - // When we act as server, consider the channel open when we've sent the + // When we act as server, consider the channel open when we've sent the // confirmation message to the peer IsOpen = true; } diff --git a/src/Renci.SshNet/CipherInfo.cs b/src/Renci.SshNet/CipherInfo.cs index 2641437b0..81e5e0689 100644 --- a/src/Renci.SshNet/CipherInfo.cs +++ b/src/Renci.SshNet/CipherInfo.cs @@ -30,7 +30,7 @@ public class CipherInfo public CipherInfo(int keySize, Func cipher) { KeySize = keySize; - Cipher = (key, iv) => (cipher(key.Take(KeySize / 8), iv)); + Cipher = (key, iv) => cipher(key.Take(KeySize / 8), iv); } } } diff --git a/src/Renci.SshNet/ClientAuthentication.cs b/src/Renci.SshNet/ClientAuthentication.cs index f0b31f872..a8a6745e2 100644 --- a/src/Renci.SshNet/ClientAuthentication.cs +++ b/src/Renci.SshNet/ClientAuthentication.cs @@ -9,14 +9,16 @@ internal class ClientAuthentication : IClientAuthentication private readonly int _partialSuccessLimit; /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The number of times an authentication attempt with any given can result in before it is disregarded. /// is less than one. public ClientAuthentication(int partialSuccessLimit) { if (partialSuccessLimit < 1) - throw new ArgumentOutOfRangeException("partialSuccessLimit", "Cannot be less than one."); + { + throw new ArgumentOutOfRangeException(nameof(partialSuccessLimit), "Cannot be less than one."); + } _partialSuccessLimit = partialSuccessLimit; } @@ -43,9 +45,14 @@ internal int PartialSuccessLimit public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session) { if (connectionInfo == null) - throw new ArgumentNullException("connectionInfo"); + { + throw new ArgumentNullException(nameof(connectionInfo)); + } + if (session == null) - throw new ArgumentNullException("session"); + { + throw new ArgumentNullException(nameof(session)); + } session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE"); session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS"); @@ -122,6 +129,7 @@ private bool TryAuthenticate(ISession session, { authenticationResult = AuthenticationResult.Success; } + break; case AuthenticationResult.Failure: authenticationState.RecordFailure(authenticationMethod); @@ -133,7 +141,9 @@ private bool TryAuthenticate(ISession session, } if (authenticationResult == AuthenticationResult.Success) + { return true; + } } return false; @@ -181,8 +191,7 @@ public void RecordFailure(IAuthenticationMethod authenticationMethod) /// An for which to record the result of an authentication attempt. public void RecordPartialSuccess(IAuthenticationMethod authenticationMethod) { - int partialSuccessCount; - if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out partialSuccessCount)) + if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out var partialSuccessCount)) { _authenticationMethodPartialSuccessRegister[authenticationMethod] = ++partialSuccessCount; } @@ -203,11 +212,11 @@ public void RecordPartialSuccess(IAuthenticationMethod authenticationMethod) /// public int GetPartialSuccessCount(IAuthenticationMethod authenticationMethod) { - int partialSuccessCount; - if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out partialSuccessCount)) + if (_authenticationMethodPartialSuccessRegister.TryGetValue(authenticationMethod, out var partialSuccessCount)) { return partialSuccessCount; } + return 0; } @@ -270,7 +279,9 @@ public IEnumerable GetActiveAuthenticationMethods(List GetActiveAuthenticationMethods(List - /// Provides additional information for asynchronous command execution + /// Provides additional information for asynchronous command execution. /// public class CommandAsyncResult : IAsyncResult { @@ -27,8 +27,6 @@ internal CommandAsyncResult() /// Total bytes sent. public int BytesSent { get; set; } - #region IAsyncResult Members - /// /// Gets a user-defined object that qualifies or contains information about an asynchronous operation. /// @@ -36,27 +34,31 @@ internal CommandAsyncResult() public object AsyncState { get; internal set; } /// - /// Gets a that is used to wait for an asynchronous operation to complete. + /// Gets a that is used to wait for an asynchronous operation to complete. /// - /// A that is used to wait for an asynchronous operation to complete. + /// + /// A that is used to wait for an asynchronous operation to complete. + /// public WaitHandle AsyncWaitHandle { get; internal set; } /// - /// Gets a value that indicates whether the asynchronous operation completed synchronously. + /// Gets a value indicating whether the asynchronous operation completed synchronously. /// - /// true if the asynchronous operation completed synchronously; otherwise, false. + /// + /// true if the asynchronous operation completed synchronously; otherwise, false. + /// public bool CompletedSynchronously { get; internal set; } /// - /// Gets a value that indicates whether the asynchronous operation has completed. + /// Gets a value indicating whether the asynchronous operation has completed. /// - /// true if the operation is complete; otherwise, false. + /// + /// true if the operation is complete; otherwise, false. + /// public bool IsCompleted { get; internal set; } - #endregion - /// - /// Gets a value indicating whether was already called for this + /// Gets or sets a value indicating whether was already called for this /// . /// /// diff --git a/src/Renci.SshNet/Common/AsyncResult.cs b/src/Renci.SshNet/Common/AsyncResult.cs index 3466a030b..ec103552e 100644 --- a/src/Renci.SshNet/Common/AsyncResult.cs +++ b/src/Renci.SshNet/Common/AsyncResult.cs @@ -8,36 +8,18 @@ namespace Renci.SshNet.Common /// public abstract class AsyncResult : IAsyncResult { - // Fields set at construction which never change while operation is pending - private readonly AsyncCallback _asyncCallback; - - private readonly object _asyncState; - - // Field set at construction which do change after operation completes private const int StatePending = 0; private const int StateCompletedSynchronously = 1; private const int StateCompletedAsynchronously = 2; + private readonly AsyncCallback _asyncCallback; + private readonly object _asyncState; private int _completedState = StatePending; - - // Field that may or may not get set depending on usage private ManualResetEvent _asyncWaitHandle; - - // Fields set when operation completes private Exception _exception; - /// - /// Gets or sets a value indicating whether has been called on the current - /// . - /// - /// - /// true if has been called on the current ; - /// otherwise, false. - /// - public bool EndInvokeCalled { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -49,37 +31,43 @@ protected AsyncResult(AsyncCallback asyncCallback, object state) _asyncState = state; } + /// + /// Gets a value indicating whether has been called on the current . + /// + /// + /// true if has been called on the current ; + /// otherwise, false. + /// + public bool EndInvokeCalled { get; private set; } + /// /// Marks asynchronous operation as completed. /// /// The exception. - /// if set to true [completed synchronously]. + /// If set to , completed synchronously. public void SetAsCompleted(Exception exception, bool completedSynchronously) { // Passing null for exception means no error occurred; this is the common case _exception = exception; - // The m_CompletedState field MUST be set prior calling the callback + // The '_completedState' field MUST be set prior calling the callback var prevState = Interlocked.Exchange(ref _completedState, - completedSynchronously ? StateCompletedSynchronously : StateCompletedAsynchronously); + completedSynchronously ? StateCompletedSynchronously : StateCompletedAsynchronously); + if (prevState != StatePending) + { throw new InvalidOperationException("You can set a result only once"); + } // If the event exists, set it - if (_asyncWaitHandle != null) - { - _asyncWaitHandle.Set(); - } + _ = _asyncWaitHandle?.Set(); // If a callback method was set, call it - if (_asyncCallback != null) - { - _asyncCallback(this); - } + _asyncCallback?.Invoke(this); } /// - /// Waits until the asynchronous operation completes, and then returns. + /// Waits until the asynchronous operation completes, and then returns. /// internal void EndInvoke() { @@ -87,7 +75,7 @@ internal void EndInvoke() if (!IsCompleted) { // If the operation isn't done, wait for it - AsyncWaitHandle.WaitOne(); + _ = AsyncWaitHandle.WaitOne(); _asyncWaitHandle = null; // Allow early GC AsyncWaitHandle.Dispose(); } @@ -96,21 +84,28 @@ internal void EndInvoke() // Operation is done: if an exception occurred, throw it if (_exception != null) + { throw _exception; + } } - #region Implementation of IAsyncResult - /// /// Gets a user-defined object that qualifies or contains information about an asynchronous operation. /// - /// A user-defined object that qualifies or contains information about an asynchronous operation. - public object AsyncState { get { return _asyncState; } } + /// + /// A user-defined object that qualifies or contains information about an asynchronous operation. + /// + public object AsyncState + { + get { return _asyncState; } + } /// - /// Gets a value that indicates whether the asynchronous operation completed synchronously. + /// Gets a value indicating whether the asynchronous operation completed synchronously. /// - /// true if the asynchronous operation completed synchronously; otherwise, false. + /// + /// if the asynchronous operation completed synchronously; otherwise, . + /// public bool CompletedSynchronously { get { return _completedState == StateCompletedSynchronously; } @@ -119,7 +114,9 @@ public bool CompletedSynchronously /// /// Gets a that is used to wait for an asynchronous operation to complete. /// - /// A that is used to wait for an asynchronous operation to complete. + /// + /// A that is used to wait for an asynchronous operation to complete. + /// public WaitHandle AsyncWaitHandle { get @@ -128,7 +125,7 @@ public WaitHandle AsyncWaitHandle { var done = IsCompleted; var mre = new ManualResetEvent(done); - if (Interlocked.CompareExchange(ref _asyncWaitHandle, mre, null) != null) + if (Interlocked.CompareExchange(ref _asyncWaitHandle, mre, comparand: null) != null) { // Another thread created this object's event; dispose the event we just created mre.Dispose(); @@ -137,27 +134,26 @@ public WaitHandle AsyncWaitHandle { if (!done && IsCompleted) { - // If the operation wasn't done when we created - // the event but now it is done, set the event - _asyncWaitHandle.Set(); + // If the operation wasn't done when we created the event but now it is done, set the event + _ = _asyncWaitHandle.Set(); } } } + return _asyncWaitHandle; } } /// - /// Gets a value that indicates whether the asynchronous operation has completed. + /// Gets a value indicating whether the asynchronous operation has completed. /// /// - /// true if the operation is complete; otherwise, false. + /// if the operation is complete; otherwise, . + /// public bool IsCompleted { get { return _completedState != StatePending; } } - - #endregion } /// @@ -190,7 +186,7 @@ public void SetAsCompleted(TResult result, bool completedSynchronously) _result = result; // Tell the base class that the operation completed successfully (no exception) - SetAsCompleted(null, completedSynchronously); + SetAsCompleted(exception: null, completedSynchronously); } /// @@ -201,8 +197,8 @@ public void SetAsCompleted(TResult result, bool completedSynchronously) /// public new TResult EndInvoke() { - base.EndInvoke(); // Wait until operation has completed + base.EndInvoke(); // Wait until operation has completed return _result; // Return the result (if above didn't throw) } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs b/src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs index 308105d4c..790ba034a 100644 --- a/src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs +++ b/src/Renci.SshNet/Common/AuthenticationBannerEventArgs.cs @@ -1,7 +1,7 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// public class AuthenticationBannerEventArgs : AuthenticationEventArgs { diff --git a/src/Renci.SshNet/Common/AuthenticationEventArgs.cs b/src/Renci.SshNet/Common/AuthenticationEventArgs.cs index dfeadbcc1..4546d318f 100644 --- a/src/Renci.SshNet/Common/AuthenticationEventArgs.cs +++ b/src/Renci.SshNet/Common/AuthenticationEventArgs.cs @@ -7,11 +7,6 @@ namespace Renci.SshNet.Common /// public abstract class AuthenticationEventArgs : EventArgs { - /// - /// Gets the username. - /// - public string Username { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -20,5 +15,10 @@ protected AuthenticationEventArgs(string username) { Username = username; } + + /// + /// Gets the username. + /// + public string Username { get; } } } diff --git a/src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs b/src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs index f6d829123..f4b4a3d8e 100644 --- a/src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs +++ b/src/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs @@ -1,18 +1,10 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// public class AuthenticationPasswordChangeEventArgs : AuthenticationEventArgs { - /// - /// Gets or sets the new password. - /// - /// - /// The new password. - /// - public byte[] NewPassword { get; set; } - /// /// Initializes a new instance of the class. /// @@ -21,5 +13,13 @@ public AuthenticationPasswordChangeEventArgs(string username) : base(username) { } + + /// + /// Gets or sets the new password. + /// + /// + /// The new password. + /// + public byte[] NewPassword { get; set; } } } diff --git a/src/Renci.SshNet/Common/AuthenticationPrompt.cs b/src/Renci.SshNet/Common/AuthenticationPrompt.cs index 15d7a982c..5a7a9688b 100644 --- a/src/Renci.SshNet/Common/AuthenticationPrompt.cs +++ b/src/Renci.SshNet/Common/AuthenticationPrompt.cs @@ -1,27 +1,40 @@ namespace Renci.SshNet.Common { /// - /// Provides prompt information when is raised + /// Provides prompt information when is raised. /// public class AuthenticationPrompt { + /// + /// Initializes a new instance of the class. + /// + /// The sequence id. + /// if set to true the user input should be echoed. + /// The request. + public AuthenticationPrompt(int id, bool isEchoed, string request) + { + Id = id; + IsEchoed = isEchoed; + Request = request; + } + /// /// Gets the prompt sequence id. /// - public int Id { get; private set; } + public int Id { get; } /// - /// Gets or sets a value indicating whether the user input should be echoed as characters are typed. + /// Gets a value indicating whether the user input should be echoed as characters are typed. /// /// /// true if the user input should be echoed as characters are typed; otherwise, false. /// - public bool IsEchoed { get; private set; } + public bool IsEchoed { get; } /// /// Gets server information request. /// - public string Request { get; private set; } + public string Request { get; } /// /// Gets or sets server information response. @@ -30,18 +43,5 @@ public class AuthenticationPrompt /// The response. /// public string Response { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// The sequence id. - /// if set to true the user input should be echoed. - /// The request. - public AuthenticationPrompt(int id, bool isEchoed, string request) - { - Id = id; - IsEchoed = isEchoed; - Request = request; - } } } diff --git a/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs b/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs index 9e2207289..9c22c340c 100644 --- a/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs +++ b/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs @@ -3,25 +3,10 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// public class AuthenticationPromptEventArgs : AuthenticationEventArgs { - /// - /// Gets prompt language. - /// - public string Language { get; private set; } - - /// - /// Gets prompt instruction. - /// - public string Instruction { get; private set; } - - /// - /// Gets server information request prompts. - /// - public IEnumerable Prompts { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -36,5 +21,20 @@ public AuthenticationPromptEventArgs(string username, string instruction, string Language = language; Prompts = prompts; } + + /// + /// Gets prompt language. + /// + public string Language { get; } + + /// + /// Gets prompt instruction. + /// + public string Instruction { get; } + + /// + /// Gets server information request prompts. + /// + public IEnumerable Prompts { get; } } } diff --git a/src/Renci.SshNet/Common/BigInteger.cs b/src/Renci.SshNet/Common/BigInteger.cs index 611b74dde..8e8f7b514 100644 --- a/src/Renci.SshNet/Common/BigInteger.cs +++ b/src/Renci.SshNet/Common/BigInteger.cs @@ -2,8 +2,8 @@ // System.Numerics.BigInteger // // Authors: -// Rodrigo Kumpera (rkumpera@novell.com) -// Marek Safar +// Rodrigo Kumpera (rkumpera@novell.com) +// Marek Safar // // Copyright (C) 2010 Novell, Inc (http://www.novell.com) // Copyright (C) 2014 Xamarin Inc (http://www.xamarin.com) @@ -44,46 +44,39 @@ * * * ***************************************************************************/ -// -// slashdocs based on MSDN using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Globalization; + using Renci.SshNet.Abstractions; /* -Optimization - Have proper popcount function for IsPowerOfTwo - Use unsafe ops to avoid bounds check - CoreAdd could avoid some resizes by checking for equal sized array that top overflow - For bitwise operators, hoist the conditionals out of their main loop - Optimize BitScanBackward - Use a carry variable to make shift opts do half the number of array ops. - Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers -*/ + * Optimization: + * - Have proper popcount function for IsPowerOfTwo + * - Use unsafe ops to avoid bounds check + * - CoreAdd could avoid some resizes by checking for equal sized array that top overflow + * - For bitwise operators, hoist the conditionals out of their main loop + * - Optimize BitScanBackward + * - Use a carry variable to make shift opts do half the number of array ops. + * -Schoolbook multiply is O(n^2), use Karatsuba /Toom-3 for large numbers + */ namespace Renci.SshNet.Common { /// /// Represents an arbitrarily large signed integer. /// - [SuppressMessage("ReSharper", "EmptyEmbeddedStatement")] - [SuppressMessage("ReSharper", "RedundantCast")] - [SuppressMessage("ReSharper", "RedundantAssignment")] - [SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")] - [SuppressMessage("ReSharper", "MergeConditionalExpression")] public struct BigInteger : IComparable, IFormattable, IComparable, IEquatable { + private const ulong Base = 0x100000000; + private const int Bias = 1075; + private const int DecimalSignMask = unchecked((int)0x80000000); + private static readonly BigInteger ZeroSingleton = new BigInteger(0); private static readonly BigInteger OneSingleton = new BigInteger(1); private static readonly BigInteger MinusOneSingleton = new BigInteger(-1); - private const ulong Base = 0x100000000; - private const int Bias = 1075; - private const int DecimalSignMask = unchecked((int) 0x80000000); - - //LSB on [0] + // LSB on [0] private readonly uint[] _data; private readonly short _sign; @@ -95,17 +88,21 @@ public struct BigInteger : IComparable, IFormattable, IComparable, I /// /// The number of the bit used. /// - public int BitLength + public readonly int BitLength { get { if (_sign == 0) + { return 0; + } var msbIndex = _data.Length - 1; while (_data[msbIndex] == 0) + { msbIndex--; + } var msbBitCount = BitScanBackward(_data[msbIndex]) + 1; @@ -129,16 +126,22 @@ public static BigInteger ModInverse(BigInteger bi, BigInteger modulus) while (!b.IsZero) { if (b.IsOne) + { return p1; + } p0 += (a / b) * p1; a %= b; if (a.IsZero) + { break; + } if (a.IsOne) + { return modulus - p0; + } p1 += (b / a) * p0; b %= a; @@ -158,8 +161,11 @@ public static BigInteger ModInverse(BigInteger bi, BigInteger modulus) public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor) { var result = dividend % divisor; + if (result < 0) + { result += divisor; + } return result; } @@ -171,9 +177,9 @@ public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor) /// A random number of the specified length. public static BigInteger Random(int bitLength) { - var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)]; + var bytesArray = new byte[(bitLength / 8) + (((bitLength % 8) > 0) ? 1 : 0)]; CryptoAbstraction.GenerateRandom(bytesArray); - bytesArray[bytesArray.Length - 1] = (byte) (bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value + bytesArray[bytesArray.Length - 1] = (byte) (bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value return new BigInteger(bytesArray); } @@ -199,12 +205,12 @@ public BigInteger(int value) else if (value > 0) { _sign = 1; - _data = new[] {(uint) value}; + _data = new[] { (uint) value }; } else { _sign = -1; - _data = new[] {(uint) -value}; + _data = new[] { (uint) -value }; } } @@ -247,7 +253,9 @@ public BigInteger(long value) _data = new uint[high != 0 ? 2 : 1]; _data[0] = low; if (high != 0) + { _data[1] = high; + } } else { @@ -259,7 +267,9 @@ public BigInteger(long value) _data = new uint[high != 0 ? 2 : 1]; _data[0] = low; if (high != 0) + { _data[1] = high; + } } } @@ -290,7 +300,7 @@ public BigInteger(ulong value) private static bool Negative(byte[] v) { - return ((v[7] & 0x80) != 0); + return (v[7] & 0x80) != 0; } private static ushort Exponent(byte[] v) @@ -300,8 +310,8 @@ private static ushort Exponent(byte[] v) private static ulong Mantissa(byte[] v) { - var i1 = ((uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24)); - var i2 = ((uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16)); + var i1 = (uint)v[0] | ((uint)v[1] << 8) | ((uint)v[2] << 16) | ((uint)v[3] << 24); + var i2 = (uint)v[4] | ((uint)v[5] << 8) | ((uint)(v[6] & 0xF) << 16); return (ulong)((ulong)i1 | ((ulong)i2 << 32)); } @@ -313,7 +323,9 @@ private static ulong Mantissa(byte[] v) public BigInteger(double value) { if (double.IsNaN(value) || double.IsInfinity(value)) + { throw new OverflowException(); + } var bytes = BitConverter.GetBytes(value); var mantissa = Mantissa(bytes); @@ -329,7 +341,7 @@ public BigInteger(double value) } var res = Negative(bytes) ? MinusOne : One; - res = res << (exponent - 0x3ff); + res <<= exponent - 0x3ff; _sign = res._sign; _data = res._data; } @@ -350,7 +362,8 @@ public BigInteger(double value) /// Initializes a new instance of the structure using a single-precision floating-point value. /// /// A single-precision floating-point value. - public BigInteger(float value) : this((double)value) + public BigInteger(float value) + : this((double)value) { } @@ -378,9 +391,14 @@ public BigInteger(decimal value) _data = new uint[size]; _data[0] = (uint)bits[0]; if (size > 1) - _data[1] = (uint)bits[1]; + { + _data[1] = (uint) bits[1]; + } + if (size > 2) - _data[2] = (uint)bits[2]; + { + _data[2] = (uint) bits[2]; + } } /// @@ -392,7 +410,9 @@ public BigInteger(decimal value) public BigInteger(byte[] value) { if (value == null) - throw new ArgumentNullException("value"); + { + throw new ArgumentNullException(nameof(value)); + } var len = value.Length; @@ -404,9 +424,13 @@ public BigInteger(byte[] value) } if ((value[len - 1] & 0x80) != 0) + { _sign = -1; + } else + { _sign = 1; + } if (_sign == 1) { @@ -423,7 +447,9 @@ public BigInteger(byte[] value) int size; var fullWords = size = len / 4; if ((len & 0x3) != 0) + { ++size; + } _data = new uint[size]; var j = 0; @@ -434,12 +460,15 @@ public BigInteger(byte[] value) (uint) (value[j++] << 16) | (uint) (value[j++] << 24); } + size = len & 0x3; if (size > 0) { var idx = _data.Length - 1; for (var i = 0; i < size; ++i) - _data[idx] |= (uint)(value[j++] << (i * 8)); + { + _data[idx] |= (uint) (value[j++] << (i * 8)); + } } } else @@ -447,7 +476,9 @@ public BigInteger(byte[] value) int size; var fullWords = size = len / 4; if ((len & 0x3) != 0) + { ++size; + } _data = new uint[size]; @@ -467,6 +498,7 @@ public BigInteger(byte[] value) borrow = (uint)(sub >> 32) & 0x1u; _data[i] = ~word; } + size = len & 0x3; if (size > 0) @@ -484,54 +516,68 @@ public BigInteger(byte[] value) borrow = (uint)(sub >> 32) & 0x1u; if ((~word & storeMask) == 0) + { Array.Resize(ref _data, _data.Length - 1); + } else + { _data[_data.Length - 1] = ~word & storeMask; + } } - if (borrow != 0) //FIXME I believe this can't happen, can someone write a test for it? + + if (borrow != 0) + { + // FIXME I believe this can't happen, can someone write a test for it? throw new Exception("non zero final carry"); + } } } /// - /// Indicates whether the value of the current object is an even number. + /// Gets a value indicating whether the value of the current object is an even number. /// /// /// true if the value of the BigInteger object is an even number; otherwise, false. /// - public bool IsEven + public readonly bool IsEven { get { return _sign == 0 || (_data[0] & 0x1) == 0; } } /// - /// Indicates whether the value of the current object is . + /// Gets a value indicating whether the value of the current object is . /// /// /// true if the value of the object is ; /// otherwise, false. /// - public bool IsOne + public readonly bool IsOne { get { return _sign == 1 && _data.Length == 1 && _data[0] == 1; } } - - //Gem from Hacker's Delight - //Returns the number of bits set in @x - static int PopulationCount(uint x) + // Gem from Hacker's Delight + // Returns the number of bits set in @x + private static int PopulationCount(uint x) { - x = x - ((x >> 1) & 0x55555555); + x -= (x >> 1) & 0x55555555; x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; - x = x + (x >> 8); - x = x + (x >> 16); - return (int)(x & 0x0000003F); + x += x >> 8; + x += x >> 16; + return (int) (x & 0x0000003F); } - //Based on code by Zilong Tan on Ulib released under MIT license - //Returns the number of bits set in @x - static int PopulationCount(ulong x) + /// + /// Returns the number of bits set in . + /// + /// + /// The number of bits set in . + /// + /// + /// Based on code by Zilong Tan on Ulib released under MIT license. + /// + private static int PopulationCount(ulong x) { x -= (x >> 1) & 0x5555555555555555UL; x = (x & 0x3333333333333333UL) + ((x >> 2) & 0x3333333333333333UL); @@ -539,7 +585,7 @@ static int PopulationCount(ulong x) return (int)((x * 0x0101010101010101UL) >> 56); } - static int LeadingZeroCount(uint value) + private static int LeadingZeroCount(uint value) { value |= value >> 1; value |= value >> 2; @@ -549,7 +595,7 @@ static int LeadingZeroCount(uint value) return 32 - PopulationCount(value); // 32 = bits in uint } - static int LeadingZeroCount(ulong value) + private static int LeadingZeroCount(ulong value) { value |= value >> 1; value |= value >> 2; @@ -560,7 +606,7 @@ static int LeadingZeroCount(ulong value) return 64 - PopulationCount(value); // 64 = bits in ulong } - static double BuildDouble(int sign, ulong mantissa, int exponent) + private static double BuildDouble(int sign, ulong mantissa, int exponent) { const int exponentBias = 1023; const int mantissaLength = 52; @@ -581,6 +627,7 @@ static double BuildDouble(int sign, ulong mantissa, int exponent) { return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; } + if (offset < 0) { mantissa >>= -offset; @@ -596,7 +643,9 @@ static double BuildDouble(int sign, ulong mantissa, int exponent) mantissa <<= offset; exponent -= offset; } - mantissa = mantissa & mantissaMask; + + mantissa &= mantissaMask; + if ((exponent & exponentMask) == exponent) { unchecked @@ -606,49 +655,59 @@ static double BuildDouble(int sign, ulong mantissa, int exponent) { bits |= negativeMark; } + return BitConverter.Int64BitsToDouble((long)bits); } } + return sign > 0 ? double.PositiveInfinity : double.NegativeInfinity; } /// - /// Indicates whether the value of the current object is a power of two. + /// Gets a value Indicating whether the value of the current object is a power of two. /// /// /// true if the value of the object is a power of two; /// otherwise, false. /// - public bool IsPowerOfTwo + public readonly bool IsPowerOfTwo { get { - var foundBit = false; if (_sign != 1) + { return false; - //This function is pop count == 1 for positive numbers + } + + var foundBit = false; + + // This function is pop count == 1 for positive numbers foreach (var bit in _data) { var p = PopulationCount(bit); if (p > 0) { if (p > 1 || foundBit) + { return false; + } + foundBit = true; } } + return foundBit; } } /// - /// Indicates whether the value of the current object is . + /// Gets a value indicating whether the value of the current object is . /// /// /// true if the value of the object is ; /// otherwise, false. /// - public bool IsZero + public readonly bool IsZero { get { return _sign == 0; } } @@ -659,7 +718,7 @@ public bool IsZero /// /// A number that indicates the sign of the object. /// - public int Sign + public readonly int Sign { get { return _sign; } } @@ -707,21 +766,34 @@ public static BigInteger Zero public static explicit operator int(BigInteger value) { if (value._data == null) + { return 0; + } + if (value._data.Length > 1) + { throw new OverflowException(); + } + var data = value._data[0]; if (value._sign == 1) { - if (data > (uint)int.MaxValue) + if (data > (uint) int.MaxValue) + { throw new OverflowException(); + } + return (int)data; } + if (value._sign == -1) { if (data > 0x80000000u) + { throw new OverflowException(); + } + return -(int)data; } @@ -739,9 +811,15 @@ public static explicit operator int(BigInteger value) public static explicit operator uint(BigInteger value) { if (value._data == null) + { return 0; + } + if (value._data.Length > 1 || value._sign == -1) + { throw new OverflowException(); + } + return value._data[0]; } @@ -754,26 +832,32 @@ public static explicit operator uint(BigInteger value) /// public static explicit operator short(BigInteger value) { - var val = (int)value; - if (val < short.MinValue || val > short.MaxValue) + var val = (int) value; + if (val is < short.MinValue or > short.MaxValue) + { throw new OverflowException(); - return (short)val; + } + + return (short) val; } /// - /// + /// Defines an explicit conversion of a object to a 16-bit unsigned integer value. /// - /// + /// The value to convert to a 16-bit unsigned integer. /// /// An object that contains the value of the parameter. /// - [CLSCompliantAttribute(false)] + [CLSCompliant(false)] public static explicit operator ushort(BigInteger value) { - var val = (uint)value; + var val = (uint) value; if (val > ushort.MaxValue) + { throw new OverflowException(); - return (ushort)val; + } + + return (ushort) val; } /// @@ -785,10 +869,13 @@ public static explicit operator ushort(BigInteger value) /// public static explicit operator byte(BigInteger value) { - var val = (uint)value; + var val = (uint) value; if (val > byte.MaxValue) + { throw new OverflowException(); - return (byte)val; + } + + return (byte) val; } /// @@ -801,10 +888,13 @@ public static explicit operator byte(BigInteger value) [CLSCompliant(false)] public static explicit operator sbyte(BigInteger value) { - var val = (int)value; - if (val < sbyte.MinValue || val > sbyte.MaxValue) + var val = (int) value; + if (val is < sbyte.MinValue or > sbyte.MaxValue) + { throw new OverflowException(); - return (sbyte)val; + } + + return (sbyte) val; } /// @@ -817,17 +907,24 @@ public static explicit operator sbyte(BigInteger value) public static explicit operator long(BigInteger value) { if (value._data == null) + { return 0; + } if (value._data.Length > 2) + { throw new OverflowException(); + } var low = value._data[0]; if (value._data.Length == 1) { if (value._sign == 1) - return (long)low; + { + return (long) low; + } + var res = (long)low; return -res; } @@ -837,7 +934,10 @@ public static explicit operator long(BigInteger value) if (value._sign == 1) { if (high >= 0x80000000u) + { throw new OverflowException(); + } + return (((long)high) << 32) | low; } @@ -853,7 +953,10 @@ long.MinValue works fine since it's bigint encoding looks like a negative var result = -((((long)high) << 32) | (long)low); if (result > 0) + { throw new OverflowException(); + } + return result; } @@ -868,13 +971,20 @@ long.MinValue works fine since it's bigint encoding looks like a negative public static explicit operator ulong(BigInteger value) { if (value._data == null) + { return 0; + } + if (value._data.Length > 2 || value._sign == -1) + { throw new OverflowException(); + } var low = value._data[0]; if (value._data.Length == 1) + { return low; + } var high = value._data[1]; return (((ulong)high) << 32) | low; @@ -890,14 +1000,16 @@ public static explicit operator ulong(BigInteger value) public static explicit operator double(BigInteger value) { if (value._data == null) + { return 0.0; + } switch (value._data.Length) { case 1: return BuildDouble(value._sign, value._data[0], 0); case 2: - return BuildDouble(value._sign, (ulong)value._data[1] << 32 | (ulong)value._data[0], 0); + return BuildDouble(value._sign, (ulong) value._data[1] << 32 | (ulong) value._data[0], 0); default: var index = value._data.Length - 1; var word = value._data[index]; @@ -912,6 +1024,7 @@ public static explicit operator double(BigInteger value) { mantissa >>= -missing; } + return BuildDouble(value._sign, mantissa, ((value._data.Length - 2) * 32) - missing); } } @@ -925,7 +1038,7 @@ public static explicit operator double(BigInteger value) /// public static explicit operator float(BigInteger value) { - return (float)(double)value; + return (float) (double) value; } /// @@ -938,19 +1051,31 @@ public static explicit operator float(BigInteger value) public static explicit operator decimal(BigInteger value) { if (value._data == null) + { return decimal.Zero; + } var data = value._data; if (data.Length > 3) + { throw new OverflowException(); + } int lo = 0, mi = 0, hi = 0; if (data.Length > 2) - hi = (int)data[2]; + { + hi = (int) data[2]; + } + if (data.Length > 1) - mi = (int)data[1]; + { + mi = (int) data[1]; + } + if (data.Length > 0) - lo = (int)data[0]; + { + lo = (int) data[0]; + } return new decimal(lo, mi, hi, value._sign < 0, 0); } @@ -999,7 +1124,7 @@ public static implicit operator BigInteger(short value) /// /// An object that contains the value of the parameter. /// - [CLSCompliantAttribute(false)] + [CLSCompliant(false)] public static implicit operator BigInteger(ushort value) { return new BigInteger(value); @@ -1102,20 +1227,32 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator +(BigInteger left, BigInteger right) { if (left._sign == 0) + { return right; + } + if (right._sign == 0) + { return left; + } if (left._sign == right._sign) + { return new BigInteger(left._sign, CoreAdd(left._data, right._data)); + } var r = CoreCompare(left._data, right._data); if (r == 0) + { return Zero; + } - if (r > 0) //left > right + if (r > 0) + { + //left > right return new BigInteger(left._sign, CoreSub(left._data, right._data)); + } return new BigInteger(right._sign, CoreSub(right._data, left._data)); } @@ -1131,19 +1268,29 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator -(BigInteger left, BigInteger right) { if (right._sign == 0) + { return left; + } + if (left._sign == 0) - return new BigInteger((short)-right._sign, right._data); + { + return new BigInteger((short) -right._sign, right._data); + } if (left._sign == right._sign) { var r = CoreCompare(left._data, right._data); if (r == 0) + { return Zero; + } - if (r > 0) //left > right + if (r > 0) + { + // left > right return new BigInteger(left._sign, CoreSub(left._data, right._data)); + } return new BigInteger((short)-right._sign, CoreSub(right._data, left._data)); } @@ -1162,19 +1309,27 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator *(BigInteger left, BigInteger right) { if (left._sign == 0 || right._sign == 0) + { return Zero; + } if (left._data[0] == 1 && left._data.Length == 1) { if (left._sign == 1) + { return right; + } + return new BigInteger((short)-right._sign, right._data); } if (right._data[0] == 1 && right._data.Length == 1) { if (right._sign == 1) + { return left; + } + return new BigInteger((short)-left._sign, left._data); } @@ -1191,7 +1346,7 @@ public static explicit operator BigInteger(decimal value) ulong carry = 0; for (var j = 0; j < b.Length; ++j) { - carry = carry + ((ulong)ai) * b[j] + res[k]; + carry = carry + ((ulong) ai) * b[j] + res[k]; res[k++] = (uint)carry; carry >>= 32; } @@ -1206,8 +1361,11 @@ public static explicit operator BigInteger(decimal value) int m; for (m = res.Length - 1; m >= 0 && res[m] == 0; --m) ; + if (m < res.Length - 1) + { Array.Resize(ref res, m + 1); + } return new BigInteger((short) (left._sign*right._sign), res); } @@ -1224,22 +1382,29 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator /(BigInteger dividend, BigInteger divisor) { if (divisor._sign == 0) + { throw new DivideByZeroException(); + } if (dividend._sign == 0) + { return dividend; + } - uint[] quotient; - uint[] remainderValue; - - DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue); + DivModUnsigned(dividend._data, divisor._data, out var quotient, out _); int i; for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ; + if (i == -1) + { return Zero; + } + if (i < quotient.Length - 1) + { Array.Resize(ref quotient, i + 1); + } return new BigInteger((short)(dividend._sign * divisor._sign), quotient); } @@ -1255,23 +1420,30 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator %(BigInteger dividend, BigInteger divisor) { if (divisor._sign == 0) + { throw new DivideByZeroException(); + } if (dividend._sign == 0) + { return dividend; + } - uint[] quotient; - uint[] remainderValue; - - DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue); + DivModUnsigned(dividend._data, divisor._data, out _, out var remainderValue); int i; for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ; + if (i == -1) + { return Zero; + } if (i < remainderValue.Length - 1) + { Array.Resize(ref remainderValue, i + 1); + } + return new BigInteger(dividend._sign, remainderValue); } @@ -1279,14 +1451,17 @@ public static explicit operator BigInteger(decimal value) /// Negates a specified value. /// /// The value to negate. - /// + /// /// The result of the parameter multiplied by negative one (-1). /// public static BigInteger operator -(BigInteger value) { if (value._data == null) + { return value; - return new BigInteger((short)-value._sign, value._data); + } + + return new BigInteger((short) -value._sign, value._data); } /// @@ -1314,16 +1489,23 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator ++(BigInteger value) { if (value._data == null) + { return One; + } var sign = value._sign; var data = value._data; if (data.Length == 1) { if (sign == -1 && data[0] == 1) + { return Zero; + } + if (sign == 0) + { return One; + } } data = sign == -1 ? CoreSub(data, 1) : CoreAdd(data, 1); @@ -1341,16 +1523,23 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator --(BigInteger value) { if (value._data == null) + { return MinusOne; + } var sign = value._sign; var data = value._data; if (data.Length == 1) { if (sign == 1 && data[0] == 1) + { return Zero; + } + if (sign == 0) + { return MinusOne; + } } data = sign == -1 ? CoreAdd(data, 1) : CoreSub(data, 1); @@ -1369,10 +1558,14 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator &(BigInteger left, BigInteger right) { if (left._sign == 0) + { return left; + } if (right._sign == 0) + { return right; + } var a = left._data; var b = right._data; @@ -1390,7 +1583,10 @@ public static explicit operator BigInteger(decimal value) { uint va = 0; if (i < a.Length) + { va = a[i]; + } + if (ls == -1) { ac = ~va + ac; @@ -1400,7 +1596,10 @@ public static explicit operator BigInteger(decimal value) uint vb = 0; if (i < b.Length) + { vb = b[i]; + } + if (rs == -1) { bc = ~vb + bc; @@ -1421,11 +1620,16 @@ public static explicit operator BigInteger(decimal value) } for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + { return Zero; + } if (i < result.Length - 1) + { Array.Resize(ref result, i + 1); + } return new BigInteger(negRes ? (short)-1 : (short)1, result); } @@ -1441,10 +1645,14 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator |(BigInteger left, BigInteger right) { if (left._sign == 0) + { return right; + } if (right._sign == 0) + { return left; + } var a = left._data; var b = right._data; @@ -1462,7 +1670,10 @@ public static explicit operator BigInteger(decimal value) { uint va = 0; if (i < a.Length) + { va = a[i]; + } + if (ls == -1) { ac = ~va + ac; @@ -1472,7 +1683,10 @@ public static explicit operator BigInteger(decimal value) uint vb = 0; if (i < b.Length) + { vb = b[i]; + } + if (rs == -1) { bc = ~vb + bc; @@ -1493,11 +1707,16 @@ public static explicit operator BigInteger(decimal value) } for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + { return Zero; + } if (i < result.Length - 1) + { Array.Resize(ref result, i + 1); + } return new BigInteger(negRes ? (short)-1 : (short)1, result); } @@ -1513,10 +1732,14 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator ^(BigInteger left, BigInteger right) { if (left._sign == 0) + { return right; + } if (right._sign == 0) + { return left; + } var a = left._data; var b = right._data; @@ -1534,7 +1757,10 @@ public static explicit operator BigInteger(decimal value) { uint va = 0; if (i < a.Length) + { va = a[i]; + } + if (ls == -1) { ac = ~va + ac; @@ -1544,7 +1770,10 @@ public static explicit operator BigInteger(decimal value) uint vb = 0; if (i < b.Length) + { vb = b[i]; + } + if (rs == -1) { bc = ~vb + bc; @@ -1565,11 +1794,16 @@ public static explicit operator BigInteger(decimal value) } for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + { return Zero; + } if (i < result.Length - 1) + { Array.Resize(ref result, i + 1); + } return new BigInteger(negRes ? (short)-1 : (short)1, result); } @@ -1584,7 +1818,9 @@ public static explicit operator BigInteger(decimal value) public static BigInteger operator ~(BigInteger value) { if (value._data == null) + { return MinusOne; + } var data = value._data; int sign = value._sign; @@ -1619,11 +1855,16 @@ public static explicit operator BigInteger(decimal value) } for (i = result.Length - 1; i >= 0 && result[i] == 0; --i) ; + if (i == -1) + { return Zero; + } if (i < result.Length - 1) + { Array.Resize(ref result, i + 1); + } return new BigInteger(negRes ? (short)-1 : (short)1, result); } @@ -1636,8 +1877,11 @@ static int BitScanBackward(uint word) { var mask = 1u << i; if ((word & mask) == mask) + { return i; + } } + return 0; } @@ -1652,9 +1896,14 @@ static int BitScanBackward(uint word) public static BigInteger operator <<(BigInteger value, int shift) { if (shift == 0 || value._data == null) + { return value; + } + if (shift < 0) + { return value >> -shift; + } var data = value._data; int sign = value._sign; @@ -1684,7 +1933,9 @@ static int BitScanBackward(uint word) var word = data[i]; res[i + idxShift] |= word << bitShift; if (i + idxShift + 1 < res.Length) + { res[i + idxShift + 1] = word >> carryShift; + } } } @@ -1702,9 +1953,14 @@ static int BitScanBackward(uint word) public static BigInteger operator >>(BigInteger value, int shift) { if (shift == 0 || value._sign == 0) + { return value; + } + if (shift < 0) + { return value << -shift; + } var data = value._data; int sign = value._sign; @@ -1715,14 +1971,15 @@ static int BitScanBackward(uint word) var extraWords = idxShift; if (bitShift > topMostIdx) + { ++extraWords; + } + var size = data.Length - extraWords; if (size <= 0) { - if (sign == 1) - return Zero; - return MinusOne; + return sign == 1 ? Zero : MinusOne; } var res = new uint[size]; @@ -1735,7 +1992,9 @@ static int BitScanBackward(uint word) var word = data[i]; if (i - idxShift < res.Length) + { res[i - idxShift] |= word >> bitShift; + } } } else @@ -1745,14 +2004,18 @@ static int BitScanBackward(uint word) var word = data[i]; if (i - idxShift < res.Length) + { res[i - idxShift] |= word >> bitShift; + } + if (i - idxShift - 1 >= 0) + { res[i - idxShift - 1] = word << carryShift; + } } - } - //Round down instead of toward zero + // Round down instead of toward zero if (sign == -1) { for (var i = 0; i < idxShift; i++) @@ -1764,6 +2027,7 @@ static int BitScanBackward(uint word) return tmp; } } + if (bitShift > 0 && (data[idxShift] << carryShift) != 0u) { var tmp = new BigInteger((short)sign, res); @@ -1771,6 +2035,7 @@ static int BitScanBackward(uint word) return tmp; } } + return new BigInteger((short)sign, res); } @@ -1816,7 +2081,6 @@ static int BitScanBackward(uint word) return right.CompareTo(left) > 0; } - /// /// Returns a value that indicates whether a 64-bit signed integer is less than a value. /// @@ -2226,9 +2490,12 @@ static int BitScanBackward(uint word) /// public override bool Equals(object obj) { - if (!(obj is BigInteger)) + if (obj is not BigInteger other) + { return false; - return Equals((BigInteger)obj); + } + + return Equals(other); } /// @@ -2243,18 +2510,26 @@ public override bool Equals(object obj) public bool Equals(BigInteger other) { if (_sign != other._sign) + { return false; + } var alen = _data != null ? _data.Length : 0; var blen = other._data != null ? other._data.Length : 0; if (alen != blen) + { return false; + } + for (var i = 0; i < alen; ++i) { if (_data[i] != other._data[i]) + { return false; + } } + return true; } @@ -2265,7 +2540,7 @@ public bool Equals(BigInteger other) /// /// true if the signed 64-bit integer and the current instance have the same value; otherwise, false. /// - public bool Equals(long other) + public readonly bool Equals(long other) { return CompareTo(other) == 0; } @@ -2278,7 +2553,7 @@ public bool Equals(long other) /// public override string ToString() { - return ToString(10, null); + return ToString(10, provider: null); } private string ToStringWithPadding(string format, uint radix, IFormatProvider provider) @@ -2294,10 +2569,13 @@ private string ToStringWithPadding(string format, uint radix, IFormatProvider pr { return additional + baseStr; } + return "-" + additional + baseStr.Substring(1); } + return baseStr; } + return ToString(radix, provider); } @@ -2313,12 +2591,12 @@ private string ToStringWithPadding(string format, uint radix, IFormatProvider pr /// is not a valid format string. public string ToString(string format) { - return ToString(format, null); + return ToString(format, provider: null); } /// /// Converts the numeric value of the current object to its equivalent string representation - /// by using the specified culture-specific formatting information. + /// by using the specified culture-specific formatting information. /// /// An object that supplies culture-specific formatting information. /// @@ -2327,7 +2605,7 @@ public string ToString(string format) /// public string ToString(IFormatProvider provider) { - return ToString(null, provider); + return ToString(format: null, provider); } /// @@ -2343,7 +2621,9 @@ public string ToString(IFormatProvider provider) public string ToString(string format, IFormatProvider provider) { if (string.IsNullOrEmpty(format)) + { return ToString(10, provider); + } switch (format[0]) { @@ -2356,7 +2636,7 @@ public string ToString(string format, IFormatProvider provider) return ToStringWithPadding(format, 10, provider); case 'x': case 'X': - return ToStringWithPadding(format, 16, null); + return ToStringWithPadding(format, 16, provider: null); default: throw new FormatException(string.Format("format '{0}' not implemented", format)); } @@ -2380,56 +2660,77 @@ private static uint[] MakeTwoComplement(uint[] v) var idx = FirstNonFfByte(last); uint mask = 0xFF; for (var i = 1; i < idx; ++i) + { mask = (mask << 8) | 0xFF; + } res[res.Length - 1] = last & mask; return res; } - private string ToString(uint radix, IFormatProvider provider) + private readonly string ToString(uint radix, IFormatProvider provider) { const string characterSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (characterSet.Length < radix) + { throw new ArgumentException("charSet length less than radix", "characterSet"); + } + if (radix == 1) - throw new ArgumentException("There is no such thing as radix one notation", "radix"); + { + throw new ArgumentException("There is no such thing as radix one notation", nameof(radix)); + } if (_sign == 0) + { return "0"; + } + if (_data.Length == 1 && _data[0] == 1) + { return _sign == 1 ? "1" : "-1"; + } var digits = new List(1 + _data.Length * 3 / 10); BigInteger a; if (_sign == 1) + { a = this; + } else { var dt = _data; if (radix > 10) + { dt = MakeTwoComplement(dt); + } + a = new BigInteger(1, dt); } while (a != 0) { - BigInteger rem; - a = DivRem(a, radix, out rem); - digits.Add(characterSet[(int)rem]); + a = DivRem(a, radix, out var rem); + digits.Add(characterSet[(int) rem]); } if (_sign == -1 && radix == 10) { NumberFormatInfo info = null; if (provider != null) + { info = provider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo; + } + if (info != null) { var str = info.NegativeSign; for (var i = str.Length - 1; i >= 0; --i) + { digits.Add(str[i]); + } } else { @@ -2439,7 +2740,9 @@ private string ToString(uint radix, IFormatProvider provider) var last = digits[digits.Count - 1]; if (_sign == 1 && radix > 10 && (last < '0' || last > '9')) + { digits.Add('0'); + } digits.Reverse(); @@ -2457,11 +2760,11 @@ private string ToString(uint radix, IFormatProvider provider) /// is not in the correct format. public static BigInteger Parse(string value) { - Exception ex; - BigInteger result; - - if (!Parse(value, false, out result, out ex)) + if (!Parse(value, tryParse: false, out var result, out var ex)) + { throw ex; + } + return result; } @@ -2482,7 +2785,7 @@ public static BigInteger Parse(string value) /// does not comply with the input pattern specified by . public static BigInteger Parse(string value, NumberStyles style) { - return Parse(value, style, null); + return Parse(value, style, provider: null); } /// @@ -2518,11 +2821,10 @@ public static BigInteger Parse(string value, IFormatProvider provider) /// does not comply with the input pattern specified by . public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider) { - Exception exc; - BigInteger res; - - if (!Parse(value, style, provider, false, out res, out exc)) + if (!Parse(value, style, provider, tryParse: false, out var res, out var exc)) + { throw exc; + } return res; } @@ -2539,8 +2841,7 @@ public static BigInteger Parse(string value, NumberStyles style, IFormatProvider /// is null. public static bool TryParse(string value, out BigInteger result) { - Exception ex; - return Parse(value, true, out result, out ex); + return Parse(value, tryParse: true, out result, out _); } /// @@ -2561,8 +2862,7 @@ public static bool TryParse(string value, out BigInteger result) /// public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out BigInteger result) { - Exception exc; - if (!Parse(value, style, provider, true, out result, out exc)) + if (!Parse(value, style, provider, tryParse: true, out result, out _)) { result = Zero; return false; @@ -2579,14 +2879,20 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, if (value == null) { if (!tryParse) - exc = new ArgumentNullException("value"); + { + exc = new ArgumentNullException(nameof(value)); + } + return false; } if (value.Length == 0) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } @@ -2596,11 +2902,13 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, var typeNfi = typeof(NumberFormatInfo); nfi = (NumberFormatInfo) fp.GetFormat(typeNfi); } - if (nfi == null) - nfi = NumberFormatInfo.CurrentInfo; + + nfi ??= NumberFormatInfo.CurrentInfo; if (!CheckStyle(style, tryParse, ref exc)) + { return false; + } var allowCurrencySymbol = (style & NumberStyles.AllowCurrencySymbol) != 0; var allowHexSpecifier = (style & NumberStyles.AllowHexSpecifier) != 0; @@ -2615,8 +2923,10 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, var pos = 0; - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } var foundOpenParentheses = false; var negative = false; @@ -2628,23 +2938,31 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, { foundOpenParentheses = true; foundSign = true; - negative = true; // MS always make the number negative when there parentheses - // even when NumberFormatInfo.NumberNegativePattern != 0!!! + negative = true; // MS always make the number negative when there parentheses, even when NumberFormatInfo.NumberNegativePattern != 0 pos++; - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + + if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } if (value.Substring(pos, nfi.NegativeSign.Length) == nfi.NegativeSign) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } if (value.Substring(pos, nfi.PositiveSign.Length) == nfi.PositiveSign) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } } @@ -2655,15 +2973,18 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, FindSign(ref pos, value, nfi, ref foundSign, ref negative); if (foundSign) { - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } + if (allowCurrencySymbol) { - FindCurrency(ref pos, value, nfi, - ref foundCurrency); - if (foundCurrency && allowLeadingWhite && - !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + FindCurrency(ref pos, value, nfi, ref foundCurrency); + if (foundCurrency && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } } } } @@ -2674,17 +2995,20 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, FindCurrency(ref pos, value, nfi, ref foundCurrency); if (foundCurrency) { - if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + if (allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } + if (foundCurrency) { if (!foundSign && allowLeadingSign) { - FindSign(ref pos, value, nfi, ref foundSign, - ref negative); - if (foundSign && allowLeadingWhite && - !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + FindSign(ref pos, value, nfi, ref foundSign, ref negative); + if (foundSign && allowLeadingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } } } } @@ -2698,13 +3022,14 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, // Number stuff while (pos < value.Length) { - if (!ValidDigit(value[pos], allowHexSpecifier)) { if (allowThousands && (FindOther(ref pos, value, nfi.NumberGroupSeparator) || FindOther(ref pos, value, nfi.CurrencyGroupSeparator))) + { continue; + } if (allowDecimalPoint && decimalPointPos < 0 && (FindOther(ref pos, value, nfi.NumberDecimalSeparator) @@ -2724,32 +3049,43 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, var hexDigit = value[pos++]; byte digitValue; if (char.IsDigit(hexDigit)) - digitValue = (byte)(hexDigit - '0'); + { + digitValue = (byte) (hexDigit - '0'); + } else if (char.IsLower(hexDigit)) - digitValue = (byte)(hexDigit - 'a' + 10); + { + digitValue = (byte) (hexDigit - 'a' + 10); + } else - digitValue = (byte)(hexDigit - 'A' + 10); + { + digitValue = (byte) (hexDigit - 'A' + 10); + } if (firstHexDigit && digitValue >= 8) + { negative = true; + } - number = number * 16 + digitValue; + number = (number * 16) + digitValue; firstHexDigit = false; continue; } - number = number * 10 + (byte)(value[pos++] - '0'); + number = (number * 10) + (byte)(value[pos++] - '0'); } // Post number stuff if (nDigits == 0) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } - //Signed hex value (Two's Complement) + // Signed hex value (Two's Complement) if (allowHexSpecifier && negative) { var mask = Pow(16, nDigits) - 1; @@ -2758,8 +3094,12 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, var exponent = 0; if (allowExponent) + { if (FindExponent(ref pos, value, ref exponent, tryParse, ref exc) && exc != null) + { return false; + } + } if (allowTrailingSign && !foundSign) { @@ -2767,65 +3107,86 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, FindSign(ref pos, value, nfi, ref foundSign, ref negative); if (foundSign && pos < value.Length) { - if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } } } if (allowCurrencySymbol && !foundCurrency) { - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc)) + if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) + { return false; + } // Currency + sign FindCurrency(ref pos, value, nfi, ref foundCurrency); if (foundCurrency && pos < value.Length) { - if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, true, tryParse, ref exc)) + if (allowTrailingWhite && !JumpOverWhitespace(ref pos, value, reportError: true, tryParse, ref exc)) + { return false; + } + if (!foundSign && allowTrailingSign) - FindSign(ref pos, value, nfi, ref foundSign, - ref negative); + { + FindSign(ref pos, value, nfi, ref foundSign, ref negative); + } } } - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc)) + if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) + { return false; + } if (foundOpenParentheses) { if (pos >= value.Length || value[pos++] != ')') { if (!tryParse) + { exc = GetFormatException(); + } + return false; } - if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, false, tryParse, ref exc)) + + if (allowTrailingWhite && pos < value.Length && !JumpOverWhitespace(ref pos, value, reportError: false, tryParse, ref exc)) + { return false; + } } if (pos < value.Length && value[pos] != '\u0000') { if (!tryParse) + { exc = GetFormatException(); + } + return false; } if (decimalPointPos >= 0) + { exponent = exponent - nDigits + decimalPointPos; + } if (exponent < 0) { - // // Any non-zero values after decimal point are not allowed - // - BigInteger remainder; - number = DivRem(number, Pow(10, -exponent), out remainder); + number = DivRem(number, Pow(10, -exponent), out var remainder); if (!remainder.IsZero) { if (!tryParse) + { exc = new OverflowException("Value too large or too small. exp=" + exponent + " rem = " + remainder + " pow = " + Pow(10, -exponent)); + } + return false; } } @@ -2835,11 +3196,17 @@ private static bool Parse(string value, NumberStyles style, IFormatProvider fp, } if (number._sign == 0) + { result = number; + } else if (negative) + { result = new BigInteger(-1, number._data); + } else + { result = new BigInteger(1, number._data); + } return true; } @@ -2850,23 +3217,34 @@ private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception { var ne = style ^ NumberStyles.AllowHexSpecifier; if ((ne & NumberStyles.AllowLeadingWhite) != 0) + { ne ^= NumberStyles.AllowLeadingWhite; + } + if ((ne & NumberStyles.AllowTrailingWhite) != 0) + { ne ^= NumberStyles.AllowTrailingWhite; + } + if (ne != 0) { if (!tryParse) - exc = new ArgumentException( - "With AllowHexSpecifier only " + - "AllowLeadingWhite and AllowTrailingWhite " + - "are permitted."); + { + exc = new ArgumentException("With AllowHexSpecifier only " + + "AllowLeadingWhite and AllowTrailingWhite " + + "are permitted."); + } + return false; } } else if ((uint)style > (uint)NumberStyles.Any) { if (!tryParse) + { exc = new ArgumentException("Not a valid number style"); + } + return false; } @@ -2876,12 +3254,17 @@ private static bool CheckStyle(NumberStyles style, bool tryParse, ref Exception private static bool JumpOverWhitespace(ref int pos, string s, bool reportError, bool tryParse, ref Exception exc) { while (pos < s.Length && char.IsWhiteSpace(s[pos])) + { pos++; + } if (reportError && pos >= s.Length) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } @@ -2960,8 +3343,8 @@ private static bool FindExponent(ref int pos, string s, ref int exponent, bool t } // Reduce the risk of throwing an overflow exc - exp = checked(exp * 10 - (int)(s[i] - '0')); - if (exp < int.MinValue || exp > int.MaxValue) + exp = checked((exp * 10) - (int)(s[i] - '0')); + if (exp is < int.MinValue or > int.MaxValue) { exc = tryParse ? null : new OverflowException("Value too large or too small."); return true; @@ -2970,7 +3353,9 @@ private static bool FindExponent(ref int pos, string s, ref int exponent, bool t // exp value saved as negative if (!negative) + { exp = -exp; + } exc = null; exponent = (int) exp; @@ -2993,7 +3378,9 @@ private static bool FindOther(ref int pos, string s, string other) private static bool ValidDigit(char e, bool allowHex) { if (allowHex) + { return char.IsDigit(e) || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } return char.IsDigit(e); } @@ -3014,10 +3401,14 @@ private static bool ProcessTrailingWhitespace(bool tryParse, string s, int posit if (c != 0 && !char.IsWhiteSpace(c)) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } } + return true; } @@ -3032,7 +3423,10 @@ private static bool Parse(string value, bool tryParse, out BigInteger result, ou if (value == null) { if (!tryParse) - exc = new ArgumentNullException("value"); + { + exc = new ArgumentNullException(nameof(value)); + } + return false; } @@ -3043,13 +3437,18 @@ private static bool Parse(string value, bool tryParse, out BigInteger result, ou { c = value[i]; if (!char.IsWhiteSpace(c)) + { break; + } } if (i == len) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } @@ -3059,7 +3458,9 @@ private static bool Parse(string value, bool tryParse, out BigInteger result, ou var positive = info.PositiveSign; if (string.CompareOrdinal(value, i, positive, 0, positive.Length) == 0) + { i += positive.Length; + } else if (string.CompareOrdinal(value, i, negative, 0, negative.Length) == 0) { sign = -1; @@ -3077,31 +3478,42 @@ private static bool Parse(string value, bool tryParse, out BigInteger result, ou continue; } - if (c >= '0' && c <= '9') + if (c is >= '0' and <= '9') { - var d = (byte)(c - '0'); + var d = (byte) (c - '0'); - val = val * 10 + d; + val = (val * 10) + d; digitsSeen = true; } else if (!ProcessTrailingWhitespace(tryParse, value, i, ref exc)) + { return false; + } } if (!digitsSeen) { if (!tryParse) + { exc = GetFormatException(); + } + return false; } if (val._sign == 0) + { result = val; + } else if (sign == -1) + { result = new BigInteger(-1, val._data); + } else + { result = new BigInteger(1, val._data); + } return true; } @@ -3120,16 +3532,26 @@ public static BigInteger Min(BigInteger left, BigInteger right) int rs = right._sign; if (ls < rs) + { return left; + } + if (rs < ls) + { return right; + } var r = CoreCompare(left._data, right._data); if (ls == -1) + { r = -r; + } if (r <= 0) + { return left; + } + return right; } @@ -3147,16 +3569,26 @@ public static BigInteger Max(BigInteger left, BigInteger right) int rs = right._sign; if (ls > rs) + { return left; + } + if (rs > ls) + { return right; + } var r = CoreCompare(left._data, right._data); if (ls == -1) + { r = -r; + } if (r >= 0) + { return left; + } + return right; } @@ -3169,7 +3601,7 @@ public static BigInteger Max(BigInteger left, BigInteger right) /// public static BigInteger Abs(BigInteger value) { - return new BigInteger((short)Math.Abs(value._sign), value._data); + return new BigInteger((short) Math.Abs(value._sign), value._data); } /// @@ -3185,7 +3617,9 @@ public static BigInteger Abs(BigInteger value) public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out BigInteger remainder) { if (divisor._sign == 0) + { throw new DivideByZeroException(); + } if (dividend._sign == 0) { @@ -3193,13 +3627,11 @@ public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out Big return dividend; } - uint[] quotient; - uint[] remainderValue; - - DivModUnsigned(dividend._data, divisor._data, out quotient, out remainderValue); + DivModUnsigned(dividend._data, divisor._data, out var quotient, out var remainderValue); int i; for (i = remainderValue.Length - 1; i >= 0 && remainderValue[i] == 0; --i) ; + if (i == -1) { remainder = Zero; @@ -3207,15 +3639,24 @@ public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out Big else { if (i < remainderValue.Length - 1) + { Array.Resize(ref remainderValue, i + 1); + } + remainder = new BigInteger(dividend._sign, remainderValue); } for (i = quotient.Length - 1; i >= 0 && quotient[i] == 0; --i) ; + if (i == -1) + { return Zero; + } + if (i < quotient.Length - 1) + { Array.Resize(ref quotient, i + 1); + } return new BigInteger((short)(dividend._sign * divisor._sign), quotient); } @@ -3231,23 +3672,37 @@ public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out Big public static BigInteger Pow(BigInteger value, int exponent) { if (exponent < 0) - throw new ArgumentOutOfRangeException("exponent", "exp must be >= 0"); + { + throw new ArgumentOutOfRangeException(nameof(exponent), "exp must be >= 0"); + } + if (exponent == 0) + { return One; + } + if (exponent == 1) + { return value; + } var result = One; while (exponent != 0) { if ((exponent & 1) != 0) - result = result * value; + { + result *= value; + } + if (exponent == 1) + { break; + } - value = value * value; + value *= value; exponent >>= 1; } + return result; } @@ -3265,24 +3720,34 @@ public static BigInteger Pow(BigInteger value, int exponent) public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigInteger modulus) { if (exponent._sign == -1) - throw new ArgumentOutOfRangeException("exponent", "power must be >= 0"); + { + throw new ArgumentOutOfRangeException(nameof(exponent), "power must be >= 0"); + } + if (modulus._sign == 0) + { throw new DivideByZeroException(); + } var result = One % modulus; while (exponent._sign != 0) { if (!exponent.IsEven) { - result = result * value; - result = result % modulus; + result *= value; + result %= modulus; } + if (exponent.IsOne) + { break; - value = value * value; - value = value % modulus; + } + + value *= value; + value %= modulus; exponent >>= 1; } + return result; } @@ -3297,13 +3762,24 @@ public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigIntege public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right) { if (left._sign != 0 && left._data.Length == 1 && left._data[0] == 1) + { return One; + } + if (right._sign != 0 && right._data.Length == 1 && right._data[0] == 1) + { return One; + } + if (left.IsZero) + { return Abs(right); + } + if (right.IsZero) + { return Abs(left); + } var x = new BigInteger(1, left._data); var y = new BigInteger(1, right._data); @@ -3317,14 +3793,18 @@ public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right y = g; } - if (x.IsZero) return g; + + if (x.IsZero) + { + return g; + } // TODO: should we have something here if we can convert to long? - // - // Now we can just do it with single precision. I am using the binary gcd method, - // as it should be faster. - // + /* + * Now we can just do it with single precision. I am using the binary gcd method, + * as it should be faster. + */ var yy = x._data[0]; var xx = (uint)(y % yy); @@ -3333,24 +3813,40 @@ public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right while (((xx | yy) & 1) == 0) { - xx >>= 1; yy >>= 1; t++; + xx >>= 1; + yy >>= 1; + t++; } + while (xx != 0) { - while ((xx & 1) == 0) xx >>= 1; - while ((yy & 1) == 0) yy >>= 1; + while ((xx & 1) == 0) + { + xx >>= 1; + } + + while ((yy & 1) == 0) + { + yy >>= 1; + } + if (xx >= yy) + { xx = (xx - yy) >> 1; + } else + { yy = (yy - xx) >> 1; + } } return yy << t; } - /*LAMESPEC Log doesn't specify to how many ulp is has to be precise - We are equilavent to MS with about 2 ULP - */ + /* + * LAMESPEC Log doesn't specify to how many ulp is has to be precise + * We are equilavent to MS with about 2 ULP + */ /// /// Returns the logarithm of a specified number in a specified base. @@ -3358,20 +3854,26 @@ We are equilavent to MS with about 2 ULP /// A number whose logarithm is to be found. /// The base of the logarithm. /// - /// The base logarithm of value, + /// The base logarithm of value. /// /// The log of is out of range of the data type. public static double Log(BigInteger value, double baseValue) { if (value._sign == -1 || baseValue == 1.0d || baseValue == -1.0d || baseValue == double.NegativeInfinity || double.IsNaN(baseValue)) + { return double.NaN; + } - if (baseValue == 0.0d || baseValue == double.PositiveInfinity) + if (baseValue is 0.0d or double.PositiveInfinity) + { return value.IsOne ? 0 : double.NaN; + } if (value._data == null) + { return double.NegativeInfinity; + } var length = value._data.Length - 1; var bitCount = -1; @@ -3391,19 +3893,24 @@ public static double Log(BigInteger value, double baseValue) var tempBitlen = bitlen; while (tempBitlen > int.MaxValue) { - testBit = testBit << int.MaxValue; + testBit <<= int.MaxValue; tempBitlen -= int.MaxValue; } - testBit = testBit << (int)tempBitlen; + + testBit <<= (int)tempBitlen; for (var curbit = bitlen; curbit >= 0; --curbit) { if ((value & testBit)._sign != 0) + { c += d; + } + d *= 0.5; - testBit = testBit >> 1; + testBit >>= 1; } - return (Math.Log(c) + Math.Log(2) * bitlen) / Math.Log(baseValue); + + return (Math.Log(c) + (Math.Log(2) * bitlen)) / Math.Log(baseValue); } /// @@ -3440,7 +3947,7 @@ public static double Log10(BigInteger value) /// true if the current instance and the unsigned 64-bit integer have the same value; otherwise, false. /// [CLSCompliant(false)] - public bool Equals(ulong other) + public readonly bool Equals(ulong other) { return CompareTo(other) == 0; } @@ -3451,16 +3958,18 @@ public bool Equals(ulong other) /// /// A 32-bit signed integer hash code. /// - public override int GetHashCode() + public override readonly int GetHashCode() { - var hash = (uint)(_sign * 0x01010101u); + var hash = (uint) (_sign * 0x01010101u); if (_data != null) { foreach (var bit in _data) + { hash ^= bit; + } } - return (int)hash; + return (int) hash; } /// @@ -3568,15 +4077,19 @@ public static BigInteger Negate(BigInteger value) /// /// /// is not a . - public int CompareTo(object obj) + public readonly int CompareTo(object obj) { if (obj == null) + { return 1; + } - if (!(obj is BigInteger)) + if (obj is not BigInteger other) + { return -1; + } - return Compare(this, (BigInteger)obj); + return Compare(this, other); } /// @@ -3606,7 +4119,7 @@ public int CompareTo(object obj) /// /// /// - public int CompareTo(BigInteger other) + public readonly int CompareTo(BigInteger other) { return Compare(this, other); } @@ -3639,15 +4152,22 @@ public int CompareTo(BigInteger other) /// /// [CLSCompliant(false)] - public int CompareTo(ulong other) + public readonly int CompareTo(ulong other) { if (_sign < 0) + { return -1; + } + if (_sign == 0) + { return other == 0 ? 0 : -1; + } if (_data.Length > 2) + { return 1; + } var high = (uint)(other >> 32); var low = (uint)other; @@ -3655,23 +4175,36 @@ public int CompareTo(ulong other) return LongCompare(low, high); } - private int LongCompare(uint low, uint high) + private readonly int LongCompare(uint low, uint high) { uint h = 0; + if (_data.Length > 1) + { h = _data[1]; + } if (h > high) + { return 1; + } + if (h < high) + { return -1; + } var l = _data[0]; if (l > low) + { return 1; + } + if (l < low) + { return -1; + } return 0; } @@ -3703,28 +4236,39 @@ private int LongCompare(uint low, uint high) /// /// /// - public int CompareTo(long other) + public readonly int CompareTo(long other) { int ls = _sign; var rs = Math.Sign(other); if (ls != rs) + { return ls > rs ? 1 : -1; + } if (ls == 0) + { return 0; + } if (_data.Length > 2) + { return _sign; + } if (other < 0) + { other = -other; - var low = (uint)other; - var high = (uint)((ulong)other >> 32); + } + + var low = (uint) other; + var high = (uint) ((ulong) other >> 32); var r = LongCompare(low, high); if (ls == -1) + { r = -r; + } return r; } @@ -3761,11 +4305,16 @@ public static int Compare(BigInteger left, BigInteger right) int rs = right._sign; if (ls != rs) + { return ls > rs ? 1 : -1; + } var r = CoreCompare(left._data, right._data); if (ls < 0) + { r = -r; + } + return r; } @@ -3774,22 +4323,38 @@ private static int TopByte(uint x) if ((x & 0xFFFF0000u) != 0) { if ((x & 0xFF000000u) != 0) + { return 4; + } + return 3; } + if ((x & 0xFF00u) != 0) + { return 2; + } + return 1; } private static int FirstNonFfByte(uint word) { if ((word & 0xFF000000u) != 0xFF000000u) + { return 4; + } + if ((word & 0xFF0000u) != 0xFF0000u) + { return 3; + } + if ((word & 0xFF00u) != 0xFF00u) + { return 2; + } + return 1; } @@ -3799,19 +4364,21 @@ private static int FirstNonFfByte(uint word) /// /// The value of the current object converted to an array of bytes. /// - public byte[] ToByteArray() + public readonly byte[] ToByteArray() { if (_sign == 0) + { return new byte[1]; + } - //number of bytes not counting upper word + // number of bytes not counting upper word var bytes = (_data.Length - 1) * 4; var needExtraZero = false; var topWord = _data[_data.Length - 1]; int extra; - //if the topmost bit is set we need an extra + // if the topmost bit is set we need an extra if (_sign == 1) { extra = TopByte(topWord); @@ -3840,6 +4407,7 @@ public byte[] ToByteArray() res[j++] = (byte)(word >> 16); res[j++] = (byte)(word >> 24); } + while (extra-- > 0) { res[j++] = (byte)topWord; @@ -3866,7 +4434,7 @@ public byte[] ToByteArray() res[j++] = (byte)(word >> 24); } - add = (ulong)~topWord + (carry); + add = (ulong)~topWord + carry; word = (uint)add; carry = (uint)(add >> 32); if (carry == 0) @@ -3876,15 +4444,20 @@ public byte[] ToByteArray() var to = ex + (needExtra ? 1 : 0); if (to != extra) + { Array.Resize(ref res, bytes + to); + } while (ex-- > 0) { res[j++] = (byte)word; word >>= 8; } + if (needExtra) + { res[j++] = 0xFF; + } } else { @@ -3926,7 +4499,7 @@ private static uint[] CoreAdd(uint[] a, uint[] b) for (; i < bl; i++) { - sum = sum + a[i]; + sum += a[i]; res[i] = (uint)sum; sum >>= 32; } @@ -3965,10 +4538,12 @@ private static uint[] CoreSub(uint[] a, uint[] b) borrow = (borrow >> 32) & 0x1; } - //remove extra zeroes + // remove extra zeroes for (i = bl - 1; i >= 0 && res[i] == 0; --i) ; if (i < bl - 1) + { Array.Resize(ref res, i + 1); + } return res; } @@ -3982,7 +4557,7 @@ private static uint[] CoreAdd(uint[] a, uint b) int i; for (i = 0; i < len; i++) { - sum = sum + a[i]; + sum += a[i]; res[i] = (uint)sum; sum >>= 32; } @@ -4010,10 +4585,12 @@ private static uint[] CoreSub(uint[] a, uint b) borrow = (borrow >> 32) & 0x1; } - //remove extra zeroes + // Remove extra zeroes for (i = len - 1; i >= 0 && res[i] == 0; --i) ; if (i < len - 1) + { Array.Resize(ref res, i + 1); + } return res; } @@ -4024,19 +4601,30 @@ private static int CoreCompare(uint[] a, uint[] b) var bl = b != null ? b.Length : 0; if (al > bl) + { return 1; + } + if (bl > al) + { return -1; + } for (var i = al - 1; i >= 0; --i) { var ai = a[i]; var bi = b[i]; if (ai > bi) + { return 1; + } + if (ai < bi) + { return -1; + } } + return 0; } @@ -4044,11 +4632,35 @@ private static int GetNormalizeShift(uint value) { var shift = 0; - if ((value & 0xFFFF0000) == 0) { value <<= 16; shift += 16; } - if ((value & 0xFF000000) == 0) { value <<= 8; shift += 8; } - if ((value & 0xF0000000) == 0) { value <<= 4; shift += 4; } - if ((value & 0xC0000000) == 0) { value <<= 2; shift += 2; } - if ((value & 0x80000000) == 0) { value <<= 1; shift += 1; } + if ((value & 0xFFFF0000) == 0) + { + value <<= 16; + shift += 16; + } + + if ((value & 0xFF000000) == 0) + { + value <<= 8; + shift += 8; + } + + if ((value & 0xF0000000) == 0) + { + value <<= 4; + shift += 4; + } + + if ((value & 0xC0000000) == 0) + { + value <<= 2; + shift += 2; + } + + if ((value & 0x80000000) == 0) + { + value <<= 1; + shift += 1; + } return shift; } @@ -4099,7 +4711,7 @@ private static void Unnormalize(uint[] un, out uint[] r, int shift) { var uni = un[i]; r[i] = (uni >> shift) | carry; - carry = (uni << lshift); + carry = uni << lshift; } } else @@ -4118,8 +4730,7 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] if (n <= 1) { - // Divide by single digit - // + // Divide by single digit ulong rem = 0; var v0 = v[0]; q = new uint[m]; @@ -4134,6 +4745,7 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] rem -= div * v0; q[j] = (uint)div; } + r[0] = (uint)rem; } else if (m >= n) @@ -4149,8 +4761,7 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] q = new uint[m - n + 1]; r = null; - // Main division loop - // + // Main division loop for (var j = m - n; j >= 0; j--) { int i; @@ -4162,20 +4773,21 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] for (;;) { // Estimate too big ? - // if ((qq >= Base) || (qq * vn[n - 2] > (rr * Base + un[j + n - 2]))) { qq--; rr += (ulong)vn[n - 1]; if (rr < Base) + { continue; + } } + break; } - // Multiply and subtract - // + // Multiply and subtract long b = 0; long t = 0; for (i = 0; i < n; i++) @@ -4187,15 +4799,14 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] t >>= 32; b = (long)p - t; } + t = (long)un[j + n] - b; un[j + n] = (uint)t; - // Store the calculated value - // + // Store the calculated value q[j] = (uint)qq; - // Add back vn[0..n] to un[j..j+n] - // + // Add back vn[0..n] to un[j..j+n] if (t < 0) { q[j]--; @@ -4206,6 +4817,7 @@ private static void DivModUnsigned(uint[] u, uint[] v, out uint[] q, out uint[] un[j + i] = (uint)c; c >>= 32; } + c += (ulong)un[j + n]; un[j + n] = (uint)c; } diff --git a/src/Renci.SshNet/Common/ChannelDataEventArgs.cs b/src/Renci.SshNet/Common/ChannelDataEventArgs.cs index 6b47eb6ed..4891fe240 100644 --- a/src/Renci.SshNet/Common/ChannelDataEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelDataEventArgs.cs @@ -1,15 +1,10 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// internal class ChannelDataEventArgs : ChannelEventArgs { - /// - /// Gets channel data. - /// - public byte[] Data { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -20,5 +15,10 @@ public ChannelDataEventArgs(uint channelNumber, byte[] data) { Data = data; } + + /// + /// Gets channel data. + /// + public byte[] Data { get; } } } diff --git a/src/Renci.SshNet/Common/ChannelEventArgs.cs b/src/Renci.SshNet/Common/ChannelEventArgs.cs index a8e4549ce..ef514fd29 100644 --- a/src/Renci.SshNet/Common/ChannelEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelEventArgs.cs @@ -7,11 +7,6 @@ namespace Renci.SshNet.Common /// internal class ChannelEventArgs : EventArgs { - /// - /// Gets the channel number. - /// - public uint ChannelNumber { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -20,5 +15,13 @@ public ChannelEventArgs(uint channelNumber) { ChannelNumber = channelNumber; } + + /// + /// Gets the channel number. + /// + /// + /// The channel number. + /// + public uint ChannelNumber { get; } } } diff --git a/src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs b/src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs index 9098d6b1b..b5eadffe1 100644 --- a/src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelExtendedDataEventArgs.cs @@ -1,7 +1,7 @@ namespace Renci.SshNet.Common { /// - /// Provides data for events. + /// Provides data for events. /// internal class ChannelExtendedDataEventArgs : ChannelDataEventArgs { @@ -11,7 +11,8 @@ internal class ChannelExtendedDataEventArgs : ChannelDataEventArgs /// Channel number. /// Channel data. /// Channel data type code. - public ChannelExtendedDataEventArgs(uint channelNumber, byte[] data, uint dataTypeCode) : base(channelNumber, data) + public ChannelExtendedDataEventArgs(uint channelNumber, byte[] data, uint dataTypeCode) + : base(channelNumber, data) { DataTypeCode = dataTypeCode; } @@ -19,6 +20,9 @@ public ChannelExtendedDataEventArgs(uint channelNumber, byte[] data, uint dataTy /// /// Gets the data type code. /// - public uint DataTypeCode { get; private set; } + /// + /// The data type code. + /// + public uint DataTypeCode { get; } } } diff --git a/src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs b/src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs index bd10d8258..9af1e782d 100644 --- a/src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelOpenConfirmedEventArgs.cs @@ -1,7 +1,7 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// internal class ChannelOpenConfirmedEventArgs : ChannelEventArgs { @@ -24,7 +24,7 @@ public ChannelOpenConfirmedEventArgs(uint remoteChannelNumber, uint initialWindo /// /// The initial size of the window. /// - public uint InitialWindowSize { get; private set; } + public uint InitialWindowSize { get; } /// /// Gets the maximum size of the packet. @@ -32,6 +32,6 @@ public ChannelOpenConfirmedEventArgs(uint remoteChannelNumber, uint initialWindo /// /// The maximum size of the packet. /// - public uint MaximumPacketSize { get; private set; } + public uint MaximumPacketSize { get; } } } diff --git a/src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs b/src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs index f130a59eb..43b5790c6 100644 --- a/src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelOpenFailedEventArgs.cs @@ -1,25 +1,10 @@ namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// internal class ChannelOpenFailedEventArgs : ChannelEventArgs { - /// - /// Gets failure reason code. - /// - public uint ReasonCode { get; private set; } - - /// - /// Gets failure description. - /// - public string Description { get; private set; } - - /// - /// Gets failure language. - /// - public string Language { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -34,5 +19,20 @@ public ChannelOpenFailedEventArgs(uint channelNumber, uint reasonCode, string de Description = description; Language = language; } + + /// + /// Gets failure reason code. + /// + public uint ReasonCode { get; } + + /// + /// Gets failure description. + /// + public string Description { get; } + + /// + /// Gets failure language. + /// + public string Language { get; } } } diff --git a/src/Renci.SshNet/Common/ChannelRequestEventArgs.cs b/src/Renci.SshNet/Common/ChannelRequestEventArgs.cs index 0de905a83..b03102aef 100644 --- a/src/Renci.SshNet/Common/ChannelRequestEventArgs.cs +++ b/src/Renci.SshNet/Common/ChannelRequestEventArgs.cs @@ -1,18 +1,14 @@ using System; + using Renci.SshNet.Messages.Connection; namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// internal class ChannelRequestEventArgs : EventArgs { - /// - /// Gets request information. - /// - public RequestInfo Info { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -21,5 +17,13 @@ public ChannelRequestEventArgs(RequestInfo info) { Info = info; } + + /// + /// Gets the request information. + /// + /// + /// The request information. + /// + public RequestInfo Info { get; } } } diff --git a/src/Renci.SshNet/Common/DerData.cs b/src/Renci.SshNet/Common/DerData.cs index 35178798a..ee6c07e36 100644 --- a/src/Renci.SshNet/Common/DerData.cs +++ b/src/Renci.SshNet/Common/DerData.cs @@ -16,39 +16,17 @@ public class DerData private const byte Octetstring = 0x04; private const byte Null = 0x05; private const byte Objectidentifier = 0x06; - //private const byte EXTERNAL = 0x08; - //private const byte ENUMERATED = 0x0a; private const byte Sequence = 0x10; - //private const byte SEQUENCEOF = 0x10; // for completeness - //private const byte SET = 0x11; - //private const byte SETOF = 0x11; // for completeness - - //private const byte NUMERICSTRING = 0x12; - //private const byte PRINTABLESTRING = 0x13; - //private const byte T61STRING = 0x14; - //private const byte VIDEOTEXSTRING = 0x15; - //private const byte IA5STRING = 0x16; - //private const byte UTCTIME = 0x17; - //private const byte GENERALIZEDTIME = 0x18; - //private const byte GRAPHICSTRING = 0x19; - //private const byte VISIBLESTRING = 0x1a; - //private const byte GENERALSTRING = 0x1b; - //private const byte UNIVERSALSTRING = 0x1c; - //private const byte BMPSTRING = 0x1e; - //private const byte UTF8STRING = 0x0c; - //private const byte APPLICATION = 0x40; - //private const byte TAGGED = 0x80; private readonly List _data; - - private int _readerIndex; private readonly int _lastIndex; + private int _readerIndex; /// /// Gets a value indicating whether end of data is reached. /// /// - /// true if end of data is reached; otherwise, false. + /// true if end of data is reached; otherwise, false. /// public bool IsEndOfData { @@ -80,7 +58,7 @@ public DerData(byte[] data, bool construct = false) } else { - ReadByte(); // skip dataType + _ = ReadByte(); // skip dataType var length = ReadLength(); _lastIndex = _readerIndex + length; } @@ -109,7 +87,9 @@ public BigInteger ReadBigInteger() { var type = ReadByte(); if (type != Integer) + { throw new InvalidOperationException(string.Format("Invalid data type, INTEGER(02) is expected, but was {0}", type.ToString("X2"))); + } var length = ReadLength(); @@ -126,14 +106,18 @@ public int ReadInteger() { var type = ReadByte(); if (type != Integer) + { throw new InvalidOperationException(string.Format("Invalid data type, INTEGER(02) is expected, but was {0}", type.ToString("X2"))); + } var length = ReadLength(); var data = ReadBytes(length); if (length > 4) + { throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes"); + } var result = 0; var shift = (length - 1) * 8; @@ -143,8 +127,6 @@ public int ReadInteger() shift -= 8; } - //return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]); - return result; } @@ -156,7 +138,9 @@ public byte[] ReadOctetString() { var type = ReadByte(); if (type != Octetstring) + { throw new InvalidOperationException(string.Format("Invalid data type, OCTETSTRING(04) is expected, but was {0}", type.ToString("X2"))); + } var length = ReadLength(); var data = ReadBytes(length); @@ -171,7 +155,9 @@ public byte[] ReadBitString() { var type = ReadByte(); if (type != BITSTRING) + { throw new InvalidOperationException(string.Format("Invalid data type, BITSTRING(03) is expected, but was {0}", type.ToString("X2"))); + } var length = ReadLength(); var data = ReadBytes(length); @@ -186,7 +172,9 @@ public byte[] ReadObject() { var type = ReadByte(); if (type != Objectidentifier) + { throw new InvalidOperationException(string.Format("Invalid data type, OBJECT(06) is expected, but was {0}", type.ToString("X2"))); + } var length = ReadLength(); var data = ReadBytes(length); @@ -261,7 +249,7 @@ public void WriteBitstring(byte[] data) public void Write(ObjectIdentifier identifier) { var temp = new ulong[identifier.Identifiers.Length - 1]; - temp[0] = identifier.Identifiers[0] * 40 + identifier.Identifiers[1]; + temp[0] = (identifier.Identifiers[0] * 40) + identifier.Identifiers[1]; Buffer.BlockCopy(identifier.Identifiers, 2 * sizeof(ulong), temp, 1 * sizeof(ulong), (identifier.Identifiers.Length - 2) * sizeof(ulong)); var bytes = new List(); foreach (var subidentifier in temp) @@ -275,7 +263,10 @@ public void Write(ObjectIdentifier identifier) { buffer[bufferIndex] = current; if (bufferIndex < buffer.Length - 1) + { buffer[bufferIndex] |= 0x80; + } + item >>= 7; current = (byte)(item & 0x7F); bufferIndex--; @@ -325,7 +316,7 @@ public void Write(DerData data) _data.AddRange(bytes); } - private static IEnumerable GetLength(int length) + private static byte[] GetLength(int length) { if (length > 127) { @@ -333,7 +324,9 @@ private static IEnumerable GetLength(int length) var val = length; while ((val >>= 8) != 0) + { size++; + } var data = new byte[size]; data[0] = (byte)(size | 0x80); @@ -345,12 +338,16 @@ private static IEnumerable GetLength(int length) return data; } - return new[] { (byte)length }; + + return new[] { (byte) length }; } + /// - /// Gets Data Length + /// Gets Data Length. /// - /// length + /// + /// The length. + /// public int ReadLength() { int length = ReadByte(); @@ -366,7 +363,9 @@ public int ReadLength() // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here if (size > 4) + { throw new InvalidOperationException(string.Format("DER length is '{0}' and cannot be more than 4 bytes.", size)); + } length = 0; for (var i = 0; i < size; i++) @@ -377,10 +376,9 @@ public int ReadLength() } if (length < 0) + { throw new InvalidOperationException("Corrupted data - negative length found"); - - //if (length >= limit) // after all we must have read at least 1 byte - // throw new IOException("Corrupted stream - out of bounds length found"); + } } return length; @@ -389,6 +387,7 @@ public int ReadLength() /// /// Write Byte data into internal buffer. /// + /// The data to write. public void WriteBytes(IEnumerable data) { _data.AddRange(data); @@ -397,11 +396,15 @@ public void WriteBytes(IEnumerable data) /// /// Reads Byte data into internal buffer. /// - /// data read + /// + /// The data read. + /// public byte ReadByte() { if (_readerIndex > _data.Count) + { throw new InvalidOperationException("Read out of boundaries."); + } return _data[_readerIndex++]; } @@ -409,12 +412,16 @@ public byte ReadByte() /// /// Reads lengths Bytes data into internal buffer. /// - /// data read - /// amount of data to read. + /// + /// The data read. + /// + /// amount of data to read. public byte[] ReadBytes(int length) { if (_readerIndex + length > _data.Count) + { throw new InvalidOperationException("Read out of boundaries."); + } var result = new byte[length]; _data.CopyTo(_readerIndex, result, 0, length); @@ -422,4 +429,4 @@ public byte[] ReadBytes(int length) return result; } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Common/ExceptionEventArgs.cs b/src/Renci.SshNet/Common/ExceptionEventArgs.cs index 0211be943..7e99def5a 100644 --- a/src/Renci.SshNet/Common/ExceptionEventArgs.cs +++ b/src/Renci.SshNet/Common/ExceptionEventArgs.cs @@ -7,11 +7,6 @@ namespace Renci.SshNet.Common /// public class ExceptionEventArgs : EventArgs { - /// - /// Gets the System.Exception that represents the error that occurred. - /// - public Exception Exception { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -20,5 +15,13 @@ public ExceptionEventArgs(Exception exception) { Exception = exception; } + + /// + /// Gets the that represents the error that occurred. + /// + /// + /// The that represents the error that occurred. + /// + public Exception Exception { get; } } } diff --git a/src/Renci.SshNet/Common/Extensions.cs b/src/Renci.SshNet/Common/Extensions.cs index 3a5311f07..1e6bb6def 100644 --- a/src/Renci.SshNet/Common/Extensions.cs +++ b/src/Renci.SshNet/Common/Extensions.cs @@ -11,7 +11,7 @@ namespace Renci.SshNet.Common { /// - /// Collection of different extension method + /// Collection of different extension methods. /// internal static partial class Extensions { @@ -24,12 +24,17 @@ internal static partial class Extensions /// public static bool IsNullOrWhiteSpace(this string value) { - if (string.IsNullOrEmpty(value)) return true; + if (string.IsNullOrEmpty(value)) + { + return true; + } for (var i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) + { return false; + } } return true; @@ -97,7 +102,7 @@ internal static T[] Reverse(this T[] array) } /// - /// Prints out + /// Prints out the specified bytes. /// /// The bytes. internal static void DebugPrint(this IEnumerable bytes) @@ -106,8 +111,9 @@ internal static void DebugPrint(this IEnumerable bytes) foreach (var b in bytes) { - sb.AppendFormat(CultureInfo.CurrentCulture, "0x{0:x2}, ", b); + _ = sb.AppendFormat(CultureInfo.CurrentCulture, "0x{0:x2}, ", b); } + Debug.WriteLine(sb.ToString()); } @@ -117,32 +123,37 @@ internal static void DebugPrint(this IEnumerable bytes) /// The type to create. /// Type of the instance to create. /// A reference to the newly created object. - internal static T CreateInstance(this Type type) where T : class + internal static T CreateInstance(this Type type) + where T : class { if (type == null) + { return null; + } + return Activator.CreateInstance(type) as T; } internal static void ValidatePort(this uint value, string argument) { if (value > IPEndPoint.MaxPort) + { throw new ArgumentOutOfRangeException(argument, - string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.", - IPEndPoint.MaxPort)); + string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.", IPEndPoint.MaxPort)); + } } internal static void ValidatePort(this int value, string argument) { if (value < IPEndPoint.MinPort) - throw new ArgumentOutOfRangeException(argument, - string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.", - IPEndPoint.MinPort)); + { + throw new ArgumentOutOfRangeException(argument, string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.", IPEndPoint.MinPort)); + } if (value > IPEndPoint.MaxPort) - throw new ArgumentOutOfRangeException(argument, - string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.", - IPEndPoint.MaxPort)); + { + throw new ArgumentOutOfRangeException(argument, string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.", IPEndPoint.MaxPort)); + } } /// @@ -163,13 +174,19 @@ internal static void ValidatePort(this int value, string argument) public static byte[] Take(this byte[] value, int offset, int count) { if (value == null) - throw new ArgumentNullException("value"); + { + throw new ArgumentNullException(nameof(value)); + } if (count == 0) + { return Array.Empty; + } if (offset == 0 && value.Length == count) + { return value; + } var taken = new byte[count]; Buffer.BlockCopy(value, offset, taken, 0, count); @@ -192,13 +209,19 @@ public static byte[] Take(this byte[] value, int offset, int count) public static byte[] Take(this byte[] value, int count) { if (value == null) - throw new ArgumentNullException("value"); + { + throw new ArgumentNullException(nameof(value)); + } if (count == 0) + { return Array.Empty; + } if (value.Length == count) + { return value; + } var taken = new byte[count]; Buffer.BlockCopy(value, 0, taken, 0, count); @@ -208,20 +231,31 @@ public static byte[] Take(this byte[] value, int count) public static bool IsEqualTo(this byte[] left, byte[] right) { if (left == null) - throw new ArgumentNullException("left"); + { + throw new ArgumentNullException(nameof(left)); + } + if (right == null) - throw new ArgumentNullException("right"); + { + throw new ArgumentNullException(nameof(right)); + } if (left == right) + { return true; + } if (left.Length != right.Length) + { return false; + } for (var i = 0; i < left.Length; i++) { if (left[i] != right[i]) + { return false; + } } return true; @@ -237,16 +271,22 @@ public static bool IsEqualTo(this byte[] left, byte[] right) public static byte[] TrimLeadingZeros(this byte[] value) { if (value == null) - throw new ArgumentNullException("value"); + { + throw new ArgumentNullException(nameof(value)); + } for (var i = 0; i < value.Length; i++) { if (value[i] == 0) + { continue; + } // if the first byte is non-zero, then we return the byte array as is if (i == 0) + { return value; + } var remainingBytes = value.Length - i; @@ -266,7 +306,10 @@ public static byte[] TrimLeadingZeros(this byte[] value) public static byte[] Pad(this byte[] data, int length) { if (length <= data.Length) + { return data; + } + var newData = new byte[length]; Buffer.BlockCopy(data, 0, newData, newData.Length - data.Length, data.Length); return newData; @@ -275,10 +318,14 @@ public static byte[] Pad(this byte[] data, int length) public static byte[] Concat(this byte[] first, byte[] second) { if (first == null || first.Length == 0) + { return second; + } if (second == null || second.Length == 0) + { return first; + } var concat = new byte[first.Length + second.Length]; Buffer.BlockCopy(first, 0, concat, 0, first.Length); @@ -299,7 +346,10 @@ internal static bool CanWrite(this Socket socket) internal static bool IsConnected(this Socket socket) { if (socket == null) + { return false; + } + return socket.Connected; } } diff --git a/src/Renci.SshNet/Common/HostKeyEventArgs.cs b/src/Renci.SshNet/Common/HostKeyEventArgs.cs index 7f0d6befc..017b1e513 100644 --- a/src/Renci.SshNet/Common/HostKeyEventArgs.cs +++ b/src/Renci.SshNet/Common/HostKeyEventArgs.cs @@ -46,12 +46,9 @@ public class HostKeyEventArgs : EventArgs /// The host. public HostKeyEventArgs(KeyHostAlgorithm host) { - CanTrust = true; // Set default value - + CanTrust = true; HostKey = host.Data; - HostKeyName = host.Name; - KeyLength = host.Key.KeyLength; using (var md5 = CryptoAbstraction.CreateMD5()) diff --git a/src/Renci.SshNet/Common/NetConfServerException.cs b/src/Renci.SshNet/Common/NetConfServerException.cs index 86fbeabef..39f3f8eb7 100644 --- a/src/Renci.SshNet/Common/NetConfServerException.cs +++ b/src/Renci.SshNet/Common/NetConfServerException.cs @@ -34,8 +34,8 @@ public NetConfServerException(string message) /// /// The message. /// The inner exception. - public NetConfServerException(string message, Exception innerException) : - base(message, innerException) + public NetConfServerException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/ObjectIdentifier.cs b/src/Renci.SshNet/Common/ObjectIdentifier.cs index 3ff128bc6..ab491cce6 100644 --- a/src/Renci.SshNet/Common/ObjectIdentifier.cs +++ b/src/Renci.SshNet/Common/ObjectIdentifier.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Common { /// - /// Describes object identifier for DER encoding + /// Describes object identifier for DER encoding. /// public struct ObjectIdentifier { @@ -13,14 +13,22 @@ public struct ObjectIdentifier public ulong[] Identifiers { get; private set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the struct. /// /// The identifiers. + /// is . + /// has less than two elements. public ObjectIdentifier(params ulong[] identifiers) - : this() { + if (identifiers == null) + { + throw new ArgumentNullException(nameof(identifiers)); + } + if (identifiers.Length < 2) - throw new ArgumentException("identifiers"); + { + throw new ArgumentException("Must contain at least two elements.", nameof(identifiers)); + } Identifiers = identifiers; } diff --git a/src/Renci.SshNet/Common/PacketDump.cs b/src/Renci.SshNet/Common/PacketDump.cs index cd68549d6..c9357a3af 100644 --- a/src/Renci.SshNet/Common/PacketDump.cs +++ b/src/Renci.SshNet/Common/PacketDump.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Common { - internal class PacketDump + internal static class PacketDump { public static string Create(List data, int indentLevel) { @@ -15,9 +15,14 @@ public static string Create(List data, int indentLevel) public static string Create(byte[] data, int indentLevel) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } + if (indentLevel < 0) - throw new ArgumentOutOfRangeException("indentLevel", "Cannot be less than zero."); + { + throw new ArgumentOutOfRangeException(nameof(indentLevel), "Cannot be less than zero."); + } const int lineWidth = 16; @@ -31,12 +36,12 @@ public static string Create(byte[] data, int indentLevel) if (result.Length > 0) { - result.Append(Environment.NewLine); + _ = result.Append(Environment.NewLine); } - result.Append(indentChars); - result.Append(pos.ToString("X8")); - result.Append(" "); + _ = result.Append(indentChars); + _ = result.Append(pos.ToString("X8")); + _ = result.Append(" "); while (true) { @@ -48,10 +53,11 @@ public static string Create(byte[] data, int indentLevel) } } - result.Append(AsHex(line, linePos)); - result.Append(" "); - result.Append(AsAscii(line, linePos)); + _ = result.Append(AsHex(line, linePos)); + _ = result.Append(" "); + _ = result.Append(AsAscii(line, linePos)); } + return result.ToString(); } @@ -63,15 +69,15 @@ private static string AsHex(byte[] data, int length) { if (i > 0) { - hex.Append(' '); + _ = hex.Append(' '); } - hex.Append(data[i].ToString("X2", CultureInfo.InvariantCulture)); + _ = hex.Append(data[i].ToString("X2", CultureInfo.InvariantCulture)); } if (length < data.Length) { - hex.Append(new string(' ', (data.Length - length) * 3)); + _ = hex.Append(new string(' ', (data.Length - length) * 3)); } return hex.ToString(); @@ -88,17 +94,17 @@ private static string AsAscii(byte[] data, int length) { var b = data[i]; - if (b < 32 || b >= 127) + if (b is < 32 or >= 127) { - ascii.Append(dot); + _ = ascii.Append(dot); } else { - ascii.Append(encoding.GetString(data, i, 1)); + _ = ascii.Append(encoding.GetString(data, i, 1)); } } return ascii.ToString(); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Common/PipeStream.cs b/src/Renci.SshNet/Common/PipeStream.cs index fac54fb62..71a82e1d8 100644 --- a/src/Renci.SshNet/Common/PipeStream.cs +++ b/src/Renci.SshNet/Common/PipeStream.cs @@ -1,40 +1,38 @@ -namespace Renci.SshNet.Common -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Threading; - using System.Globalization; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Threading; +namespace Renci.SshNet.Common +{ /// - /// PipeStream is a thread-safe read/write data stream for use between two threads in a + /// PipeStream is a thread-safe read/write data stream for use between two threads in a /// single-producer/single-consumer type problem. /// /// 2006/10/13 1.0 /// Update on 2008/10/9 1.1 - uses Monitor instead of Manual Reset events for more elegant synchronicity. /// - /// Copyright (c) 2006 James Kolpack (james dot kolpack at google mail) - /// - /// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - /// associated documentation files (the "Software"), to deal in the Software without restriction, - /// including without limitation the rights to use, copy, modify, merge, publish, distribute, - /// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - /// furnished to do so, subject to the following conditions: - /// - /// The above copyright notice and this permission notice shall be included in all copies or - /// substantial portions of the Software. - /// - /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - /// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - /// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - /// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT - /// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - /// OTHER DEALINGS IN THE SOFTWARE. + /// Copyright (c) 2006 James Kolpack (james dot kolpack at google mail) + /// + /// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + /// associated documentation files (the "Software"), to deal in the Software without restriction, + /// including without limitation the rights to use, copy, modify, merge, publish, distribute, + /// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + /// furnished to do so, subject to the following conditions: + /// + /// The above copyright notice and this permission notice shall be included in all copies or + /// substantial portions of the Software. + /// + /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + /// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + /// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + /// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + /// OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + /// OTHER DEALINGS IN THE SOFTWARE. /// public class PipeStream : Stream { - #region Private members - /// /// Queue of bytes provides the datastructure for transmitting from an /// input stream to an output stream. @@ -64,10 +62,6 @@ public class PipeStream : Stream /// private bool _isDisposed; - #endregion - - #region Public properties - /// /// Gets or sets the maximum number of bytes to store in the buffer. /// @@ -87,7 +81,7 @@ public long MaxBufferLength /// Setting to true will remove the possibility of ending a stream reader prematurely. /// /// - /// true if block last read method before the buffer is empty; otherwise, false. + /// true if block last read method before the buffer is empty; otherwise, false. /// /// Methods were called after the stream was closed. public bool BlockLastReadBuffer @@ -95,28 +89,32 @@ public bool BlockLastReadBuffer get { if (_isDisposed) + { throw CreateObjectDisposedException(); + } return _canBlockLastRead; } set { if (_isDisposed) + { throw CreateObjectDisposedException(); + } _canBlockLastRead = value; // when turning off the block last read, signal Read() that it may now read the rest of the buffer. if (!_canBlockLastRead) + { lock (_buffer) + { Monitor.Pulse(_buffer); + } + } } } - #endregion - - #region Stream overide methods - /// /// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device. /// @@ -129,7 +127,9 @@ public bool BlockLastReadBuffer public override void Flush() { if (_isDisposed) + { throw CreateObjectDisposedException(); + } _isFlushed = true; lock (_buffer) @@ -163,37 +163,57 @@ public override void SetLength(long value) throw new NotSupportedException(); } - /// - ///When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. - /// - /// - ///The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the stream is closed or end of the stream has been reached. - /// - ///The zero-based byte offset in buffer at which to begin storing the data read from the current stream. - ///The maximum number of bytes to be read from the current stream. - ///An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. - ///The sum of offset and count is larger than the buffer length. - ///Methods were called after the stream was closed. - ///The stream does not support reading. - /// is null. - ///An I/O error occurs. - ///offset or count is negative. + /// + /// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read. + /// + /// + /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the stream is closed or end of the stream has been reached. + /// + /// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source. + /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. + /// The maximum number of bytes to be read from the current stream. + /// The sum of offset and count is larger than the buffer length. + /// Methods were called after the stream was closed. + /// The stream does not support reading. + /// is null. + /// An I/O error occurs. + /// offset or count is negative. public override int Read(byte[] buffer, int offset, int count) { if (offset != 0) + { throw new NotSupportedException("Offsets with value of non-zero are not supported"); + } + if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset + count > buffer.Length) + { throw new ArgumentException("The sum of offset and count is greater than the buffer length."); + } + if (offset < 0 || count < 0) - throw new ArgumentOutOfRangeException("offset", "offset or count is negative."); + { + throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative."); + } + if (BlockLastReadBuffer && count >= _maxBufferLength) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "count({0}) > mMaxBufferLength({1})", count, _maxBufferLength)); + } + if (_isDisposed) + { throw CreateObjectDisposedException(); + } + if (count == 0) + { return 0; + } var readLength = 0; @@ -201,7 +221,7 @@ public override int Read(byte[] buffer, int offset, int count) { while (!_isDisposed && !ReadAvailable(count)) { - Monitor.Wait(_buffer); + _ = Monitor.Wait(_buffer); } // return zero when the read is interrupted by a close/dispose of the stream @@ -223,46 +243,64 @@ public override int Read(byte[] buffer, int offset, int count) } /// - /// Returns true if there are + /// Returns a value indicating whether data is available. /// /// The count. - /// True if data available; otherwisefalse. + /// + /// if data is available; otherwise, . + /// private bool ReadAvailable(int count) { var length = Length; return (_isFlushed || length >= count) && (length >= (count + 1) || !BlockLastReadBuffer); } - /// - ///When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. - /// - ///The zero-based byte offset in buffer at which to begin copying bytes to the current stream. - ///The number of bytes to be written to the current stream. - ///An array of bytes. This method copies count bytes from buffer to the current stream. - ///An I/O error occurs. - ///The stream does not support writing. - ///Methods were called after the stream was closed. - /// is null. - ///The sum of offset and count is greater than the buffer length. - ///offset or count is negative. + /// + /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. + /// + /// An array of bytes. This method copies count bytes from buffer to the current stream. + /// The zero-based byte offset in buffer at which to begin copying bytes to the current stream. + /// The number of bytes to be written to the current stream. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. + /// is null. + /// The sum of offset and count is greater than the buffer length. + /// offset or count is negative. public override void Write(byte[] buffer, int offset, int count) { if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset + count > buffer.Length) + { throw new ArgumentException("The sum of offset and count is greater than the buffer length."); + } + if (offset < 0 || count < 0) - throw new ArgumentOutOfRangeException("offset", "offset or count is negative."); + { + throw new ArgumentOutOfRangeException(nameof(offset), "offset or count is negative."); + } + if (_isDisposed) + { throw CreateObjectDisposedException(); + } + if (count == 0) + { return; + } lock (_buffer) { // wait until the buffer isn't full while (Length >= _maxBufferLength) - Monitor.Wait(_buffer); + { + _ = Monitor.Wait(_buffer); + } _isFlushed = false; // if it were flushed before, it soon will not be. @@ -297,30 +335,30 @@ protected override void Dispose(bool disposing) } } - /// - ///When overridden in a derived class, gets a value indicating whether the current stream supports reading. - /// - /// - ///true if the stream supports reading; otherwise, false. - /// + /// + /// Gets a value indicating whether the current stream supports reading. + /// + /// + /// true if the stream supports reading; otherwise, false. + /// public override bool CanRead { get { return !_isDisposed; } } /// - /// When overridden in a derived class, gets a value indicating whether the current stream supports seeking. + /// Gets a value indicating whether the current stream supports seeking. /// /// /// true if the stream supports seeking; otherwise, false. - /// + /// public override bool CanSeek { get { return false; } } /// - /// When overridden in a derived class, gets a value indicating whether the current stream supports writing. + /// Gets a value indicating whether the current stream supports writing. /// /// /// true if the stream supports writing; otherwise, false. @@ -331,7 +369,7 @@ public override bool CanWrite } /// - /// When overridden in a derived class, gets the length in bytes of the stream. + /// Gets the length in bytes of the stream. /// /// /// A long value representing the length of the stream in bytes. @@ -343,14 +381,16 @@ public override long Length get { if (_isDisposed) + { throw CreateObjectDisposedException(); + } return _buffer.Count; } } /// - /// When overridden in a derived class, gets or sets the position within the current stream. + /// Gets or sets the position within the current stream. /// /// /// The current position within the stream. @@ -362,8 +402,6 @@ public override long Position set { throw new NotSupportedException(); } } - #endregion - private ObjectDisposedException CreateObjectDisposedException() { return new ObjectDisposedException(GetType().FullName); diff --git a/src/Renci.SshNet/Common/PortForwardEventArgs.cs b/src/Renci.SshNet/Common/PortForwardEventArgs.cs index 96a7f8255..4d1f1656d 100644 --- a/src/Renci.SshNet/Common/PortForwardEventArgs.cs +++ b/src/Renci.SshNet/Common/PortForwardEventArgs.cs @@ -1,37 +1,41 @@ using System; +using System.Net; namespace Renci.SshNet.Common { /// - /// Provides data for event. + /// Provides data for event. /// public class PortForwardEventArgs : EventArgs { - /// - /// Gets request originator host. - /// - public string OriginatorHost { get; private set; } - - /// - /// Gets request originator port. - /// - public uint OriginatorPort { get; private set; } - /// /// Initializes a new instance of the class. /// /// The host. /// The port. /// is null. - /// is not within and . + /// is not within and . internal PortForwardEventArgs(string host, uint port) { if (host == null) - throw new ArgumentNullException("host"); + { + throw new ArgumentNullException(nameof(host)); + } + port.ValidatePort("port"); OriginatorHost = host; OriginatorPort = port; } + + /// + /// Gets request originator host. + /// + public string OriginatorHost { get; } + + /// + /// Gets request originator port. + /// + public uint OriginatorPort { get; } } } diff --git a/src/Renci.SshNet/Common/PosixPath.cs b/src/Renci.SshNet/Common/PosixPath.cs index 465916b3a..2d028bd67 100644 --- a/src/Renci.SshNet/Common/PosixPath.cs +++ b/src/Renci.SshNet/Common/PosixPath.cs @@ -2,16 +2,45 @@ namespace Renci.SshNet.Common { + /// + /// Represents a POSIX path. + /// internal class PosixPath { + private PosixPath() + { + } + + /// + /// Gets the directory of the path. + /// + /// + /// The directory of the path. + /// public string Directory { get; private set; } + + /// + /// Gets the file part of the path. + /// + /// + /// The file part of the path, or if the path represents a directory. + /// public string File { get; private set; } + /// + /// Create a from the specified path. + /// + /// The path. + /// + /// A created from the specified path. + /// + /// is . + /// is empty (""). public static PosixPath CreateAbsoluteOrRelativeFilePath(string path) { if (path == null) { - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); } var posixPath = new PosixPath(); @@ -21,7 +50,7 @@ public static PosixPath CreateAbsoluteOrRelativeFilePath(string path) { if (path.Length == 0) { - throw new ArgumentException("The path is a zero-length string.", "path"); + throw new ArgumentException("The path is a zero-length string.", nameof(path)); } posixPath.Directory = "."; @@ -54,7 +83,7 @@ public static PosixPath CreateAbsoluteOrRelativeFilePath(string path) /// /// The file name part of . /// - /// is null. + /// is null. /// /// /// If contains no forward slash, then @@ -67,13 +96,21 @@ public static PosixPath CreateAbsoluteOrRelativeFilePath(string path) public static string GetFileName(string path) { if (path == null) - throw new ArgumentNullException("path"); + { + throw new ArgumentNullException(nameof(path)); + } var pathEnd = path.LastIndexOf('/'); if (pathEnd == -1) + { return path; + } + if (pathEnd == path.Length - 1) + { return string.Empty; + } + return path.Substring(pathEnd + 1); } @@ -89,15 +126,26 @@ public static string GetFileName(string path) public static string GetDirectoryName(string path) { if (path == null) - throw new ArgumentNullException("path"); + { + throw new ArgumentNullException(nameof(path)); + } var pathEnd = path.LastIndexOf('/'); if (pathEnd == -1) + { return "."; + } + if (pathEnd == 0) + { return "/"; + } + if (pathEnd == path.Length - 1) + { return path.Substring(0, pathEnd); + } + return path.Substring(0, pathEnd); } } diff --git a/src/Renci.SshNet/Common/ProxyException.cs b/src/Renci.SshNet/Common/ProxyException.cs index efb387b45..371f4f7a6 100644 --- a/src/Renci.SshNet/Common/ProxyException.cs +++ b/src/Renci.SshNet/Common/ProxyException.cs @@ -14,14 +14,14 @@ namespace Renci.SshNet.Common public class ProxyException : SshException { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public ProxyException() { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. public ProxyException(string message) @@ -30,12 +30,12 @@ public ProxyException(string message) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// The inner exception. - public ProxyException(string message, Exception innerException) : - base(message, innerException) + public ProxyException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/ScpDownloadEventArgs.cs b/src/Renci.SshNet/Common/ScpDownloadEventArgs.cs index 95ddcd638..59c6312af 100644 --- a/src/Renci.SshNet/Common/ScpDownloadEventArgs.cs +++ b/src/Renci.SshNet/Common/ScpDownloadEventArgs.cs @@ -7,21 +7,6 @@ namespace Renci.SshNet.Common /// public class ScpDownloadEventArgs : EventArgs { - /// - /// Gets the downloaded filename. - /// - public string Filename { get; private set; } - - /// - /// Gets the downloaded file size. - /// - public long Size { get; private set; } - - /// - /// Gets number of downloaded bytes so far. - /// - public long Downloaded { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -34,5 +19,20 @@ public ScpDownloadEventArgs(string filename, long size, long downloaded) Size = size; Downloaded = downloaded; } + + /// + /// Gets the downloaded filename. + /// + public string Filename { get; } + + /// + /// Gets the downloaded file size. + /// + public long Size { get; } + + /// + /// Gets number of downloaded bytes so far. + /// + public long Downloaded { get; } } } diff --git a/src/Renci.SshNet/Common/ScpException.cs b/src/Renci.SshNet/Common/ScpException.cs index e98bc688d..42d7e8d62 100644 --- a/src/Renci.SshNet/Common/ScpException.cs +++ b/src/Renci.SshNet/Common/ScpException.cs @@ -34,8 +34,8 @@ public ScpException(string message) /// /// The message. /// The inner exception. - public ScpException(string message, Exception innerException) : - base(message, innerException) + public ScpException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/ScpUploadEventArgs.cs b/src/Renci.SshNet/Common/ScpUploadEventArgs.cs index 555bdc07c..ca8514e9b 100644 --- a/src/Renci.SshNet/Common/ScpUploadEventArgs.cs +++ b/src/Renci.SshNet/Common/ScpUploadEventArgs.cs @@ -7,21 +7,6 @@ namespace Renci.SshNet.Common /// public class ScpUploadEventArgs : EventArgs { - /// - /// Gets the uploaded filename. - /// - public string Filename { get; private set; } - - /// - /// Gets the uploaded file size. - /// - public long Size { get; private set; } - - /// - /// Gets number of uploaded bytes so far. - /// - public long Uploaded { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -34,5 +19,20 @@ public ScpUploadEventArgs(string filename, long size, long uploaded) Size = size; Uploaded = uploaded; } + + /// + /// Gets the uploaded filename. + /// + public string Filename { get; } + + /// + /// Gets the uploaded file size. + /// + public long Size { get; } + + /// + /// Gets number of uploaded bytes so far. + /// + public long Uploaded { get; } } } diff --git a/src/Renci.SshNet/Common/SemaphoreLight.cs b/src/Renci.SshNet/Common/SemaphoreLight.cs index 55e4a840a..f3210c788 100644 --- a/src/Renci.SshNet/Common/SemaphoreLight.cs +++ b/src/Renci.SshNet/Common/SemaphoreLight.cs @@ -14,15 +14,17 @@ public class SemaphoreLight : IDisposable private int _currentCount; /// - /// Initializes a new instance of the class, specifying - /// the initial number of requests that can be granted concurrently. + /// Initializes a new instance of the class, specifying the initial number of requests that can + /// be granted concurrently. /// /// The initial number of requests for the semaphore that can be granted concurrently. /// is a negative number. public SemaphoreLight(int initialCount) { - if (initialCount < 0 ) - throw new ArgumentOutOfRangeException("initialCount", "The value cannot be negative."); + if (initialCount < 0) + { + throw new ArgumentOutOfRangeException(nameof(initialCount), "The value cannot be negative."); + } _currentCount = initialCount; } @@ -30,10 +32,13 @@ public SemaphoreLight(int initialCount) /// /// Gets the current count of the . /// - public int CurrentCount { get { return _currentCount; } } + public int CurrentCount + { + get { return _currentCount; } + } /// - /// Returns a that can be used to wait on the semaphore. + /// Gets a that can be used to wait on the semaphore. /// /// /// A that can be used to wait on the semaphore. @@ -51,10 +56,7 @@ public WaitHandle AvailableWaitHandle { lock (_lock) { - if (_waitHandle == null) - { - _waitHandle = new ManualResetEvent(_currentCount > 0); - } + _waitHandle ??= new ManualResetEvent(_currentCount > 0); } } @@ -89,7 +91,7 @@ public int Release(int releaseCount) // signal waithandle when the original semaphore count was zero if (_waitHandle != null && oldCount == 0) { - _waitHandle.Set(); + _ = _waitHandle.Set(); } Monitor.PulseAll(_lock); @@ -107,7 +109,7 @@ public void Wait() { while (_currentCount < 1) { - Monitor.Wait(_lock); + _ = Monitor.Wait(_lock); } _currentCount--; @@ -115,7 +117,7 @@ public void Wait() // unsignal waithandle when the semaphore count reaches zero if (_waitHandle != null && _currentCount == 0) { - _waitHandle.Reset(); + _ = _waitHandle.Reset(); } Monitor.PulseAll(_lock); @@ -133,7 +135,9 @@ public void Wait() public bool Wait(int millisecondsTimeout) { if (millisecondsTimeout < -1) - throw new ArgumentOutOfRangeException("millisecondsTimeout", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + { + throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + } return WaitWithTimeout(millisecondsTimeout); } @@ -149,8 +153,10 @@ public bool Wait(int millisecondsTimeout) public bool Wait(TimeSpan timeout) { var timeoutInMilliseconds = timeout.TotalMilliseconds; - if (timeoutInMilliseconds < -1d || timeoutInMilliseconds > int.MaxValue) - throw new ArgumentOutOfRangeException("timeout", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + if (timeoutInMilliseconds is < -1d or > int.MaxValue) + { + throw new ArgumentOutOfRangeException(nameof(timeout), "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + } return WaitWithTimeout((int) timeoutInMilliseconds); } @@ -162,14 +168,18 @@ private bool WaitWithTimeout(int timeoutInMilliseconds) if (timeoutInMilliseconds == Session.Infinite) { while (_currentCount < 1) - Monitor.Wait(_lock); + { + _ = Monitor.Wait(_lock); + } } else { if (_currentCount < 1) { if (timeoutInMilliseconds > 0) + { return false; + } var remainingTimeInMilliseconds = timeoutInMilliseconds; var startTicks = Environment.TickCount; @@ -184,7 +194,9 @@ private bool WaitWithTimeout(int timeoutInMilliseconds) var elapsed = Environment.TickCount - startTicks; remainingTimeInMilliseconds -= elapsed; if (remainingTimeInMilliseconds < 0) + { return false; + } } } } @@ -194,7 +206,7 @@ private bool WaitWithTimeout(int timeoutInMilliseconds) // unsignal waithandle when the semaphore count is zero if (_waitHandle != null && _currentCount == 0) { - _waitHandle.Reset(); + _ = _waitHandle.Reset(); } Monitor.PulseAll(_lock); @@ -204,11 +216,11 @@ private bool WaitWithTimeout(int timeoutInMilliseconds) } /// - /// Finalizes the current . + /// Finalizes an instance of the class. /// ~SemaphoreLight() { - Dispose(false); + Dispose(disposing: false); } /// @@ -216,12 +228,12 @@ private bool WaitWithTimeout(int timeoutInMilliseconds) /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected void Dispose(bool disposing) diff --git a/src/Renci.SshNet/Common/SftpPathNotFoundException.cs b/src/Renci.SshNet/Common/SftpPathNotFoundException.cs index 681a4fe5f..f56f2ea31 100644 --- a/src/Renci.SshNet/Common/SftpPathNotFoundException.cs +++ b/src/Renci.SshNet/Common/SftpPathNotFoundException.cs @@ -34,8 +34,8 @@ public SftpPathNotFoundException(string message) /// /// The message. /// The inner exception. - public SftpPathNotFoundException(string message, Exception innerException) : - base(message, innerException) + public SftpPathNotFoundException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/SftpPermissionDeniedException.cs b/src/Renci.SshNet/Common/SftpPermissionDeniedException.cs index 559c98cf3..a734bdb19 100644 --- a/src/Renci.SshNet/Common/SftpPermissionDeniedException.cs +++ b/src/Renci.SshNet/Common/SftpPermissionDeniedException.cs @@ -34,8 +34,8 @@ public SftpPermissionDeniedException(string message) /// /// The message. /// The inner exception. - public SftpPermissionDeniedException(string message, Exception innerException) : - base(message, innerException) + public SftpPermissionDeniedException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/ShellDataEventArgs.cs b/src/Renci.SshNet/Common/ShellDataEventArgs.cs index 34fea8b46..e99913d22 100644 --- a/src/Renci.SshNet/Common/ShellDataEventArgs.cs +++ b/src/Renci.SshNet/Common/ShellDataEventArgs.cs @@ -3,20 +3,10 @@ namespace Renci.SshNet.Common { /// - /// Provides data for Shell DataReceived event + /// Provides data for Shell DataReceived event. /// public class ShellDataEventArgs : EventArgs { - /// - /// Gets the data. - /// - public byte[] Data { get; private set; } - - /// - /// Gets the line data. - /// - public string Line { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -34,5 +24,15 @@ public ShellDataEventArgs(string line) { Line = line; } + + /// + /// Gets the data. + /// + public byte[] Data { get; } + + /// + /// Gets the line data. + /// + public string Line { get; } } } diff --git a/src/Renci.SshNet/Common/SshAuthenticationException.cs b/src/Renci.SshNet/Common/SshAuthenticationException.cs index 4c6f72546..260fe552d 100644 --- a/src/Renci.SshNet/Common/SshAuthenticationException.cs +++ b/src/Renci.SshNet/Common/SshAuthenticationException.cs @@ -18,7 +18,6 @@ public class SshAuthenticationException : SshException /// public SshAuthenticationException() { - } /// @@ -28,7 +27,6 @@ public SshAuthenticationException() public SshAuthenticationException(string message) : base(message) { - } /// @@ -36,8 +34,8 @@ public SshAuthenticationException(string message) /// /// The message. /// The inner exception. - public SshAuthenticationException(string message, Exception innerException) : - base(message, innerException) + public SshAuthenticationException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/SshData.cs b/src/Renci.SshNet/Common/SshData.cs index 844bace7a..0a10eee64 100644 --- a/src/Renci.SshNet/Common/SshData.cs +++ b/src/Renci.SshNet/Common/SshData.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Common { /// - /// Base ssh data serialization type + /// Base ssh data serialization type. /// public abstract class SshData { @@ -57,7 +57,7 @@ protected virtual int BufferCapacity /// Gets data bytes array. /// /// - /// A array representation of data structure. + /// A array representation of data structure. /// public byte[] GetBytes() { @@ -86,7 +86,9 @@ protected virtual void WriteBytes(SshDataStream stream) public void Load(byte[] data) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } LoadInternal(data, 0, data.Length); } @@ -101,7 +103,9 @@ public void Load(byte[] data) public void Load(byte[] data, int offset, int count) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } LoadInternal(data, offset, count); } @@ -130,7 +134,7 @@ protected byte[] ReadBytes() { var bytesLength = (int) (_stream.Length - _stream.Position); var data = new byte[bytesLength]; - _stream.Read(data, 0, bytesLength); + _ = _stream.Read(data, 0, bytesLength); return data; } @@ -142,15 +146,19 @@ protected byte[] ReadBytes() /// is greater than the internal buffer size. protected byte[] ReadBytes(int length) { - // Note that this also prevents allocating non-relevant lengths, such as if length is greater than _data.Count but less than int.MaxValue. - // For the nerds, the condition translates to: if (length > data.Count && length < int.MaxValue) - // Which probably would cause all sorts of exception, most notably OutOfMemoryException. + /* + * Note that this also prevents allocating non-relevant lengths, such as if length is greater than _data.Count but less than int.MaxValue. + * For the nerds, the condition translates to: if (length > data.Count && length < int.MaxValue) + * Which probably would cause all sorts of exception, most notably OutOfMemoryException. + */ var data = new byte[length]; var bytesRead = _stream.Read(data, 0, length); if (bytesRead < length) - throw new ArgumentOutOfRangeException("length"); + { + throw new ArgumentOutOfRangeException(nameof(length)); + } return data; } @@ -163,51 +171,63 @@ protected byte ReadByte() { var byteRead = _stream.ReadByte(); if (byteRead == -1) + { throw new InvalidOperationException("Attempt to read past the end of the SSH data stream."); + } + return (byte) byteRead; } /// - /// Reads next boolean data type from internal buffer. + /// Reads the next from the internal buffer. /// - /// Boolean read. + /// + /// The that was read. + /// protected bool ReadBoolean() { return ReadByte() != 0; } /// - /// Reads next uint16 data type from internal buffer. + /// Reads the next from the internal buffer. /// - /// uint16 read + /// + /// The that was read. + /// protected ushort ReadUInt16() { return Pack.BigEndianToUInt16(ReadBytes(2)); } /// - /// Reads next uint32 data type from internal buffer. + /// Reads the next from the internal buffer. /// - /// uint32 read + /// + /// The that was read. + /// protected uint ReadUInt32() { return Pack.BigEndianToUInt32(ReadBytes(4)); } /// - /// Reads next uint64 data type from internal buffer. + /// Reads the next from the internal buffer. /// - /// uint64 read + /// + /// The that was read. + /// protected ulong ReadUInt64() { return Pack.BigEndianToUInt64(ReadBytes(8)); } /// - /// Reads next string data type from internal buffer using the specific encoding. + /// Reads the next from the internal buffer using the specified encoding. /// + /// The character encoding to use. /// - /// The read. + /// The that was read. /// protected string ReadString(Encoding encoding) { @@ -244,12 +264,14 @@ protected string[] ReadNamesList() protected IDictionary ReadExtensionPair() { var result = new Dictionary(); + while (!IsEndOfData) { var extensionName = ReadString(Ascii); var extensionData = ReadString(Ascii); result.Add(extensionName, extensionData); } + return result; } diff --git a/src/Renci.SshNet/Common/SshDataStream.cs b/src/Renci.SshNet/Common/SshDataStream.cs index 0e024491c..54a5505f5 100644 --- a/src/Renci.SshNet/Common/SshDataStream.cs +++ b/src/Renci.SshNet/Common/SshDataStream.cs @@ -21,7 +21,7 @@ public SshDataStream(int capacity) } /// - /// Initializes a new non-resizable instance of the class based on the specified byte array. + /// Initializes a new instance of the class for the specified byte array. /// /// The array of unsigned bytes from which to create the current stream. /// is null. @@ -31,7 +31,7 @@ public SshDataStream(byte[] buffer) } /// - /// Initializes a new non-resizable instance of the class based on the specified byte array. + /// Initializes a new instance of the class for the specified byte array. /// /// The array of unsigned bytes from which to create the current stream. /// The zero-based offset in at which to begin reading SSH data. @@ -94,7 +94,9 @@ public void Write(BigInteger data) public void Write(byte[] data) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } Write(data, 0, data.Length); } @@ -125,7 +127,9 @@ public byte[] ReadBinary() public void WriteBinary(byte[] buffer) { if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } WriteBinary(buffer, 0, buffer.Length); } @@ -155,7 +159,9 @@ public void WriteBinary(byte[] buffer, int offset, int count) public void Write(string s, Encoding encoding) { if (encoding == null) - throw new ArgumentNullException("encoding"); + { + throw new ArgumentNullException(nameof(encoding)); + } var bytes = encoding.GetBytes(s); WriteBinary(bytes, 0, bytes.Length); @@ -201,6 +207,7 @@ public ulong ReadUInt64() /// /// Reads the next data type from the SSH data stream. /// + /// The character encoding to use. /// /// The read from the SSH data stream. /// @@ -217,27 +224,6 @@ public string ReadString(Encoding encoding) return encoding.GetString(bytes, 0, bytes.Length); } - /// - /// Reads next specified number of bytes data type from internal buffer. - /// - /// Number of bytes to read. - /// - /// An array of bytes that was read from the internal buffer. - /// - /// is greater than the internal buffer size. - private byte[] ReadBytes(int length) - { - var data = new byte[length]; - var bytesRead = Read(data, 0, length); - - if (bytesRead < length) - throw new ArgumentOutOfRangeException("length", - string.Format(CultureInfo.InvariantCulture, - "The requested length ({0}) is greater than the actual number of bytes read ({1}).", length, bytesRead)); - - return data; - } - /// /// Writes the stream contents to a byte array, regardless of the . /// @@ -254,7 +240,29 @@ public override byte[] ToArray() { return GetBuffer(); } + return base.ToArray(); } + + /// + /// Reads next specified number of bytes data type from internal buffer. + /// + /// Number of bytes to read. + /// + /// An array of bytes that was read from the internal buffer. + /// + /// is greater than the internal buffer size. + private byte[] ReadBytes(int length) + { + var data = new byte[length]; + var bytesRead = Read(data, 0, length); + + if (bytesRead < length) + { + throw new ArgumentOutOfRangeException(nameof(length), string.Format(CultureInfo.InvariantCulture, "The requested length ({0}) is greater than the actual number of bytes read ({1}).", length, bytesRead)); + } + + return data; + } } } diff --git a/src/Renci.SshNet/Common/SshOperationTimeoutException.cs b/src/Renci.SshNet/Common/SshOperationTimeoutException.cs index 7dff901f6..9fcce26ae 100644 --- a/src/Renci.SshNet/Common/SshOperationTimeoutException.cs +++ b/src/Renci.SshNet/Common/SshOperationTimeoutException.cs @@ -34,8 +34,8 @@ public SshOperationTimeoutException(string message) /// /// The message. /// The inner exception. - public SshOperationTimeoutException(string message, Exception innerException) : - base(message, innerException) + public SshOperationTimeoutException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs b/src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs index 1aa0f0d9d..102b585d7 100644 --- a/src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs +++ b/src/Renci.SshNet/Common/SshPassPhraseNullOrEmptyException.cs @@ -6,7 +6,7 @@ namespace Renci.SshNet.Common { /// - /// The exception that is thrown when pass phrase for key file is empty or null + /// The exception that is thrown when pass phrase for key file is empty or . /// #if FEATURE_BINARY_SERIALIZATION [Serializable] @@ -18,7 +18,6 @@ public class SshPassPhraseNullOrEmptyException : SshException /// public SshPassPhraseNullOrEmptyException() { - } /// @@ -28,7 +27,6 @@ public SshPassPhraseNullOrEmptyException() public SshPassPhraseNullOrEmptyException(string message) : base(message) { - } /// @@ -36,8 +34,8 @@ public SshPassPhraseNullOrEmptyException(string message) /// /// The message. /// The inner exception. - public SshPassPhraseNullOrEmptyException(string message, Exception innerException) : - base(message, innerException) + public SshPassPhraseNullOrEmptyException(string message, Exception innerException) + : base(message, innerException) { } diff --git a/src/Renci.SshNet/Common/TerminalModes.cs b/src/Renci.SshNet/Common/TerminalModes.cs index 98c7b8fe5..8737872b8 100644 --- a/src/Renci.SshNet/Common/TerminalModes.cs +++ b/src/Renci.SshNet/Common/TerminalModes.cs @@ -7,21 +7,21 @@ public enum TerminalModes : byte { /// /// Indicates end of options. - /// + /// TTY_OP_END = 0, - + /// /// Interrupt character; 255 if none. Similarly for the other characters. Not all of these characters are supported on all systems. - /// + /// VINTR = 1, /// /// The quit character (sends SIGQUIT signal on POSIX systems). - /// + /// VQUIT = 2, - + /// - /// Erase the character to left of the cursor. + /// Erase the character to left of the cursor. /// VERASE = 3, @@ -34,32 +34,32 @@ public enum TerminalModes : byte /// End-of-file character (sends EOF from the terminal). /// VEOF = 5, - + /// /// End-of-line character in addition to carriage return and/or linefeed. /// VEOL = 6, - + /// /// Additional end-of-line character. /// VEOL2 = 7, - + /// /// Continues paused output (normally control-Q). /// VSTART = 8, - + /// /// Pauses output (normally control-S). /// VSTOP = 9, - + /// /// Suspends the current program. /// VSUSP = 10, - + /// /// Another suspend character. /// @@ -76,7 +76,7 @@ public enum TerminalModes : byte VWERASE = 13, /// - /// Enter the next character typed literally, even if it is a special character + /// Enter the next character typed literally, even if it is a special character. /// VLNEXT = 14, diff --git a/src/Renci.SshNet/Compression/Compressor.cs b/src/Renci.SshNet/Compression/Compressor.cs index 5d06c781f..df887aa1c 100644 --- a/src/Renci.SshNet/Compression/Compressor.cs +++ b/src/Renci.SshNet/Compression/Compressor.cs @@ -1,6 +1,7 @@ -using Renci.SshNet.Security; +using System; using System.IO; -using System; + +using Renci.SshNet.Security; namespace Renci.SshNet.Compression { @@ -11,9 +12,9 @@ public abstract class Compressor : Algorithm, IDisposable { private readonly ZlibStream _compressor; private readonly ZlibStream _decompressor; - private MemoryStream _compressorStream; private MemoryStream _decompressorStream; + private bool _isDisposed; /// /// Gets or sets a value indicating whether compression is active. @@ -73,7 +74,9 @@ public virtual byte[] Compress(byte[] data, int offset, int length) if (!IsActive) { if (offset == 0 && length == data.Length) + { return data; + } var buffer = new byte[length]; Buffer.BlockCopy(data, offset, buffer, 0, length); @@ -113,7 +116,9 @@ public virtual byte[] Decompress(byte[] data, int offset, int length) if (!IsActive) { if (offset == 0 && length == data.Length) + { return data; + } var buffer = new byte[length]; Buffer.BlockCopy(data, offset, buffer, 0, length); @@ -127,16 +132,12 @@ public virtual byte[] Decompress(byte[] data, int offset, int length) return _decompressorStream.ToArray(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -147,7 +148,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -175,9 +178,7 @@ protected virtual void Dispose(bool disposing) /// ~Compressor() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/Connection/ConnectorBase.cs b/src/Renci.SshNet/Connection/ConnectorBase.cs index 6bcd556fd..1725657f5 100644 --- a/src/Renci.SshNet/Connection/ConnectorBase.cs +++ b/src/Renci.SshNet/Connection/ConnectorBase.cs @@ -1,12 +1,13 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using Renci.SshNet.Messages.Transport; -using System; +using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; +using Renci.SshNet.Messages.Transport; + namespace Renci.SshNet.Connection { internal abstract class ConnectorBase : IConnector @@ -14,7 +15,9 @@ internal abstract class ConnectorBase : IConnector protected ConnectorBase(ISocketFactory socketFactory) { if (socketFactory == null) - throw new ArgumentNullException("socketFactory"); + { + throw new ArgumentNullException(nameof(socketFactory)); + } SocketFactory = socketFactory; } @@ -95,14 +98,14 @@ protected async Task SocketConnectAsync(string host, int port, Cancellat protected static byte SocketReadByte(Socket socket) { var buffer = new byte[1]; - SocketRead(socket, buffer, 0, 1, Session.InfiniteTimeSpan); + _ = SocketRead(socket, buffer, 0, 1, Session.InfiniteTimeSpan); return buffer[0]; } protected static byte SocketReadByte(Socket socket, TimeSpan readTimeout) { var buffer = new byte[1]; - SocketRead(socket, buffer, 0, 1, readTimeout); + _ = SocketRead(socket, buffer, 0, 1, readTimeout); return buffer[0]; } @@ -145,6 +148,7 @@ protected static int SocketRead(Socket socket, byte[] buffer, int offset, int le throw new SshConnectionException("An established connection was aborted by the server.", DisconnectReason.ConnectionLost); } + return bytesRead; } } diff --git a/src/Renci.SshNet/Connection/DirectConnector.cs b/src/Renci.SshNet/Connection/DirectConnector.cs index 0f428fc31..f0b1d6d62 100644 --- a/src/Renci.SshNet/Connection/DirectConnector.cs +++ b/src/Renci.SshNet/Connection/DirectConnector.cs @@ -5,7 +5,8 @@ namespace Renci.SshNet.Connection { internal sealed class DirectConnector : ConnectorBase { - public DirectConnector(ISocketFactory socketFactory) : base(socketFactory) + public DirectConnector(ISocketFactory socketFactory) + : base(socketFactory) { } diff --git a/src/Renci.SshNet/Connection/HttpConnector.cs b/src/Renci.SshNet/Connection/HttpConnector.cs index 62c4ae279..01fa6fa10 100644 --- a/src/Renci.SshNet/Connection/HttpConnector.cs +++ b/src/Renci.SshNet/Connection/HttpConnector.cs @@ -1,11 +1,12 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using System; +using System; using System.Collections.Generic; +using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; -using System.Threading; + +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; namespace Renci.SshNet.Connection { @@ -30,7 +31,8 @@ namespace Renci.SshNet.Connection /// internal sealed class HttpConnector : ProxyConnector { - public HttpConnector(ISocketFactory socketFactory) : base(socketFactory) + public HttpConnector(ISocketFactory socketFactory) + : base(socketFactory) { } @@ -39,13 +41,17 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke var httpResponseRe = new Regex(@"HTTP/(?\d[.]\d) (?\d{3}) (?.+)$"); var httpHeaderRe = new Regex(@"(?[^\[\]()<>@,;:\""/?={} \t]+):(?.+)?"); - SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(string.Format("CONNECT {0}:{1} HTTP/1.0\r\n", connectionInfo.Host, connectionInfo.Port))); + SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(string.Format(CultureInfo.InvariantCulture, + "CONNECT {0}:{1} HTTP/1.0\r\n", + connectionInfo.Host, + connectionInfo.Port))); - // Sent proxy authorization if specified + // Send proxy authorization if specified if (!string.IsNullOrEmpty(connectionInfo.ProxyUsername)) { - var authorization = string.Format("Proxy-Authorization: Basic {0}\r\n", - Convert.ToBase64String(SshData.Ascii.GetBytes(string.Format("{0}:{1}", connectionInfo.ProxyUsername, connectionInfo.ProxyPassword)))); + var authorization = string.Format(CultureInfo.InvariantCulture, + "Proxy-Authorization: Basic {0}\r\n", + Convert.ToBase64String(SshData.Ascii.GetBytes($"{connectionInfo.ProxyUsername}:{connectionInfo.ProxyPassword}"))); SocketAbstraction.Send(socket, SshData.Ascii.GetBytes(authorization)); } @@ -69,12 +75,10 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke if (statusMatch.Success) { var httpStatusCode = statusMatch.Result("${statusCode}"); - statusCode = (HttpStatusCode)int.Parse(httpStatusCode); + statusCode = (HttpStatusCode) int.Parse(httpStatusCode, CultureInfo.InvariantCulture); if (statusCode != HttpStatusCode.OK) { - throw new ProxyException(string.Format("HTTP: Status code {0}, \"{1}\"", - httpStatusCode, - statusMatch.Result("${reasonPhrase}"))); + throw new ProxyException($"HTTP: Status code {httpStatusCode}, \"{statusMatch.Result("${reasonPhrase}")}\""); } } @@ -88,20 +92,22 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke var fieldName = headerMatch.Result("${fieldName}"); if (fieldName.Equals("Content-Length", StringComparison.OrdinalIgnoreCase)) { - contentLength = int.Parse(headerMatch.Result("${fieldValue}")); + contentLength = int.Parse(headerMatch.Result("${fieldValue}"), CultureInfo.InvariantCulture); } + continue; } // check if we've reached the CRLF which separates request line and headers from the message body if (response.Length == 0) { - // read response body if specified + // read response body if specified if (contentLength > 0) { var contentBody = new byte[contentLength]; - SocketRead(socket, contentBody, 0, contentLength, connectionInfo.Timeout); + _ = SocketRead(socket, contentBody, 0, contentLength, connectionInfo.Timeout); } + break; } } diff --git a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs index 716b8a42c..044f58715 100644 --- a/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs +++ b/src/Renci.SshNet/Connection/ProtocolVersionExchange.cs @@ -1,7 +1,4 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using Renci.SshNet.Messages.Transport; -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Net.Sockets; @@ -10,13 +7,17 @@ using System.Threading; using System.Threading.Tasks; +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; +using Renci.SshNet.Messages.Transport; + namespace Renci.SshNet.Connection { /// /// Handles the SSH protocol version exchange. /// /// - /// https://tools.ietf.org/html/rfc4253#section-4.2 + /// https://tools.ietf.org/html/rfc4253#section-4.2. /// internal class ProtocolVersionExchange : IProtocolVersionExchange { @@ -50,20 +51,10 @@ public SshIdentification Start(string clientVersion, Socket socket, TimeSpan tim { if (bytesReceived.Count == 0) { - throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string.{0}" + - "The connection to the remote server was closed before any data was received.{0}{0}" + - "More information on the Protocol Version Exchange is available here:{0}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - Environment.NewLine), - DisconnectReason.ConnectionLost); + throw CreateConnectionLostException(); } - throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string:{0}{0}{1}{0}{0}" + - "More information on the Protocol Version Exchange is available here:{0}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - Environment.NewLine, - PacketDump.Create(bytesReceived, 2)), - DisconnectReason.ProtocolError); + throw CreateServerResponseDoesNotContainIdentification(bytesReceived); } var identificationMatch = ServerVersionRe.Match(line); @@ -88,25 +79,15 @@ public async Task StartAsync(string clientVersion, Socket soc // ignore text lines which are sent before if any while (true) { - var line = await SocketReadLineAsync(socket, cancellationToken, bytesReceived).ConfigureAwait(false); + var line = await SocketReadLineAsync(socket, bytesReceived, cancellationToken).ConfigureAwait(false); if (line == null) { if (bytesReceived.Count == 0) { - throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string.{0}" + - "The connection to the remote server was closed before any data was received.{0}{0}" + - "More information on the Protocol Version Exchange is available here:{0}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - Environment.NewLine), - DisconnectReason.ConnectionLost); + throw CreateConnectionLostException(); } - throw new SshConnectionException(string.Format("The server response does not contain an SSH identification string:{0}{0}{1}{0}{0}" + - "More information on the Protocol Version Exchange is available here:{0}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - Environment.NewLine, - PacketDump.Create(bytesReceived, 2)), - DisconnectReason.ProtocolError); + throw CreateServerResponseDoesNotContainIdentification(bytesReceived); } var identificationMatch = ServerVersionRe.Match(line); @@ -164,14 +145,7 @@ private static string SocketReadLine(Socket socket, TimeSpan timeout, List // The null character MUST NOT be sent if (byteRead == Null) { - throw new SshConnectionException(string.Format(CultureInfo.InvariantCulture, - "The server response contains a null character at position 0x{0:X8}:{1}{1}{2}{1}{1}" + - "A server must not send a null character before the Protocol Version Exchange is complete.{1}{1}" + - "More information is available here:{1}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - buffer.Count, - Environment.NewLine, - PacketDump.Create(buffer.ToArray(), 2))); + throw CreateServerResponseContainsNullCharacterException(buffer); } if (byteRead == Session.LineFeed) @@ -181,21 +155,19 @@ private static string SocketReadLine(Socket socket, TimeSpan timeout, List // Return current line without CRLF return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 2)); } - else - { - // Even though RFC4253 clearly indicates that the identification string should be terminated - // by a CR LF we also support banners and identification strings that are terminated by a LF - // Return current line without LF - return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 1)); - } + // Even though RFC4253 clearly indicates that the identification string should be terminated + // by a CR LF we also support banners and identification strings that are terminated by a LF + + // Return current line without LF + return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 1)); } } return null; } - private static async Task SocketReadLineAsync(Socket socket, CancellationToken cancellationToken, List buffer) + private static async Task SocketReadLineAsync(Socket socket, List buffer, CancellationToken cancellationToken) { var data = new byte[1]; @@ -217,14 +189,7 @@ private static async Task SocketReadLineAsync(Socket socket, Cancellatio // The null character MUST NOT be sent if (byteRead == Null) { - throw new SshConnectionException(string.Format(CultureInfo.InvariantCulture, - "The server response contains a null character at position 0x{0:X8}:{1}{1}{2}{1}{1}" + - "A server must not send a null character before the Protocol Version Exchange is complete.{1}{1}" + - "More information is available here:{1}" + - "https://tools.ietf.org/html/rfc4253#section-4.2", - buffer.Count, - Environment.NewLine, - PacketDump.Create(buffer.ToArray(), 2))); + throw CreateServerResponseContainsNullCharacterException(buffer); } if (byteRead == Session.LineFeed) @@ -234,16 +199,58 @@ private static async Task SocketReadLineAsync(Socket socket, Cancellatio // Return current line without CRLF return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 2)); } - else - { - // Even though RFC4253 clearly indicates that the identification string should be terminated - // by a CR LF we also support banners and identification strings that are terminated by a LF - // Return current line without LF - return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 1)); - } + // Even though RFC4253 clearly indicates that the identification string should be terminated + // by a CR LF we also support banners and identification strings that are terminated by a LF + + // Return current line without LF + return Encoding.UTF8.GetString(buffer.ToArray(), startPosition, buffer.Count - (startPosition + 1)); } } } + + private static SshConnectionException CreateConnectionLostException() + { +#pragma warning disable SA1118 // Parameter should not span multiple lines + var message = string.Format(CultureInfo.InvariantCulture, + "The server response does not contain an SSH identification string.{0}" + + "The connection to the remote server was closed before any data was received.{0}{0}" + + "More information on the Protocol Version Exchange is available here:{0}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + Environment.NewLine); +#pragma warning restore SA1118 // Parameter should not span multiple lines + + return new SshConnectionException(message, DisconnectReason.ConnectionLost); + } + + private static SshConnectionException CreateServerResponseContainsNullCharacterException(List buffer) + { +#pragma warning disable SA1118 // Parameter should not span multiple lines + var message = string.Format(CultureInfo.InvariantCulture, + "The server response contains a null character at position 0x{0:X8}:{1}{1}{2}{1}{1}" + + "A server must not send a null character before the Protocol Version Exchange is complete.{1}{1}" + + "More information is available here:{1}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + buffer.Count, + Environment.NewLine, + PacketDump.Create(buffer.ToArray(), 2)); +#pragma warning restore SA1118 // Parameter should not span multiple lines + + throw new SshConnectionException(message); + } + + private static SshConnectionException CreateServerResponseDoesNotContainIdentification(List bytesReceived) + { +#pragma warning disable SA1118 // Parameter should not span multiple lines + var message = string.Format(CultureInfo.InvariantCulture, + "The server response does not contain an SSH identification string:{0}{0}{1}{0}{0}" + + "More information on the Protocol Version Exchange is available here:{0}" + + "https://tools.ietf.org/html/rfc4253#section-4.2", + Environment.NewLine, + PacketDump.Create(bytesReceived, 2)); +#pragma warning restore SA1118 // Parameter should not span multiple lines + + throw new SshConnectionException(message, DisconnectReason.ProtocolError); + } } } diff --git a/src/Renci.SshNet/Connection/ProxyConnector.cs b/src/Renci.SshNet/Connection/ProxyConnector.cs index 164ae4835..9bbf8b0f2 100644 --- a/src/Renci.SshNet/Connection/ProxyConnector.cs +++ b/src/Renci.SshNet/Connection/ProxyConnector.cs @@ -3,13 +3,12 @@ using System.Threading; using System.Threading.Tasks; - namespace Renci.SshNet.Connection { internal abstract class ProxyConnector : ConnectorBase { - public ProxyConnector(ISocketFactory socketFactory) : - base(socketFactory) + public ProxyConnector(ISocketFactory socketFactory) + : base(socketFactory) { } @@ -20,10 +19,11 @@ protected virtual Task HandleProxyConnectAsync(IConnectionInfo connectionInfo, S { cancellationToken.ThrowIfCancellationRequested(); - using (cancellationToken.Register(o => ((Socket)o).Dispose(), socket, false)) + using (cancellationToken.Register(o => ((Socket)o).Dispose(), socket, useSynchronizationContext: false)) { HandleProxyConnect(connectionInfo, socket); } + return Task.CompletedTask; } diff --git a/src/Renci.SshNet/Connection/Socks4Connector.cs b/src/Renci.SshNet/Connection/Socks4Connector.cs index d507872c6..046d0549b 100644 --- a/src/Renci.SshNet/Connection/Socks4Connector.cs +++ b/src/Renci.SshNet/Connection/Socks4Connector.cs @@ -1,20 +1,22 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using System; +using System; using System.Net.Sockets; using System.Text; +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; + namespace Renci.SshNet.Connection { /// /// Establishes a tunnel via a SOCKS4 proxy server. /// /// - /// https://www.openssh.com/txt/socks4.protocol + /// https://www.openssh.com/txt/socks4.protocol. /// internal sealed class Socks4Connector : ProxyConnector { - public Socks4Connector(ISocketFactory socketFactory) : base(socketFactory) + public Socks4Connector(ISocketFactory socketFactory) + : base(socketFactory) { } @@ -28,13 +30,13 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke var connectionRequest = CreateSocks4ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port, connectionInfo.ProxyUsername); SocketAbstraction.Send(socket, connectionRequest); - // Read reply version + // Read reply version if (SocketReadByte(socket, connectionInfo.Timeout) != 0x00) { throw new ProxyException("SOCKS4: Null is expected."); } - // Read response code + // Read response code var code = SocketReadByte(socket, connectionInfo.Timeout); switch (code) @@ -52,7 +54,7 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke } var destBuffer = new byte[6]; // destination port and IP address should be ignored - SocketRead(socket, destBuffer, 0, destBuffer.Length, connectionInfo.Timeout); + _ = SocketRead(socket, destBuffer, 0, destBuffer.Length, connectionInfo.Timeout); } private static byte[] CreateSocks4ConnectionRequest(string hostname, ushort port, string username) diff --git a/src/Renci.SshNet/Connection/Socks5Connector.cs b/src/Renci.SshNet/Connection/Socks5Connector.cs index e1b6859dc..9cfc4758f 100644 --- a/src/Renci.SshNet/Connection/Socks5Connector.cs +++ b/src/Renci.SshNet/Connection/Socks5Connector.cs @@ -1,19 +1,21 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using System; +using System; using System.Net.Sockets; +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; + namespace Renci.SshNet.Connection { /// /// Establishes a tunnel via a SOCKS5 proxy server. /// /// - /// https://en.wikipedia.org/wiki/SOCKS#SOCKS5 + /// https://en.wikipedia.org/wiki/SOCKS#SOCKS5. /// internal sealed class Socks5Connector : ProxyConnector { - public Socks5Connector(ISocketFactory socketFactory) : base(socketFactory) + public Socks5Connector(ISocketFactory socketFactory) + : base(socketFactory) { } @@ -51,15 +53,23 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke case 0x02: // Create username/password authentication request var authenticationRequest = CreateSocks5UserNameAndPasswordAuthenticationRequest(connectionInfo.ProxyUsername, connectionInfo.ProxyPassword); + // Send authentication request SocketAbstraction.Send(socket, authenticationRequest); + // Read authentication result var authenticationResult = SocketAbstraction.Read(socket, 2, connectionInfo.Timeout); if (authenticationResult[0] != 0x01) + { throw new ProxyException("SOCKS5: Server authentication version is not valid."); + } + if (authenticationResult[1] != 0x00) + { throw new ProxyException("SOCKS5: Username/Password authentication failed."); + } + break; case 0xFF: throw new ProxyException("SOCKS5: No acceptable authentication methods were offered."); @@ -68,13 +78,13 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke var connectionRequest = CreateSocks5ConnectionRequest(connectionInfo.Host, (ushort) connectionInfo.Port); SocketAbstraction.Send(socket, connectionRequest); - // Read Server SOCKS5 version + // Read Server SOCKS5 version if (SocketReadByte(socket) != 5) { throw new ProxyException("SOCKS5: Version 5 is expected."); } - // Read response code + // Read response code var status = SocketReadByte(socket); switch (status) @@ -101,7 +111,7 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke throw new ProxyException("SOCKS5: Not valid response."); } - // Read reserved byte + // Read reserved byte if (SocketReadByte(socket) != 0) { throw new ProxyException("SOCKS5: 0 byte is expected."); @@ -112,11 +122,11 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke { case 0x01: var ipv4 = new byte[4]; - SocketRead(socket, ipv4, 0, 4); + _ = SocketRead(socket, ipv4, 0, 4); break; case 0x04: var ipv6 = new byte[16]; - SocketRead(socket, ipv6, 0, 16); + _ =SocketRead(socket, ipv6, 0, 16); break; default: throw new ProxyException(string.Format("Address type '{0}' is not supported.", addressType)); @@ -124,19 +134,24 @@ protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socke var port = new byte[2]; - // Read 2 bytes to be ignored - SocketRead(socket, port, 0, 2); + // Read 2 bytes to be ignored + _ = SocketRead(socket, port, 0, 2); } /// - /// https://tools.ietf.org/html/rfc1929 + /// https://tools.ietf.org/html/rfc1929. /// private static byte[] CreateSocks5UserNameAndPasswordAuthenticationRequest(string username, string password) { if (username.Length > byte.MaxValue) + { throw new ProxyException("Proxy username is too long."); + } + if (password.Length > byte.MaxValue) + { throw new ProxyException("Proxy password is too long."); + } var authenticationRequest = new byte [ @@ -161,22 +176,21 @@ private static byte[] CreateSocks5UserNameAndPasswordAuthenticationRequest(strin authenticationRequest[index++] = (byte) username.Length; // Username - SshData.Ascii.GetBytes(username, 0, username.Length, authenticationRequest, index); + _ = SshData.Ascii.GetBytes(username, 0, username.Length, authenticationRequest, index); index += username.Length; // Length of the password authenticationRequest[index++] = (byte) password.Length; // Password - SshData.Ascii.GetBytes(password, 0, password.Length, authenticationRequest, index); + _ =SshData.Ascii.GetBytes(password, 0, password.Length, authenticationRequest, index); return authenticationRequest; } private static byte[] CreateSocks5ConnectionRequest(string hostname, ushort port) { - byte addressType; - var addressBytes = GetSocks5DestinationAddress(hostname, out addressType); + var addressBytes = GetSocks5DestinationAddress(hostname, out var addressType); var connectionRequest = new byte [ diff --git a/src/Renci.SshNet/Connection/SshIdentification.cs b/src/Renci.SshNet/Connection/SshIdentification.cs index 90c00fe9f..9484ea0c8 100644 --- a/src/Renci.SshNet/Connection/SshIdentification.cs +++ b/src/Renci.SshNet/Connection/SshIdentification.cs @@ -8,33 +8,38 @@ namespace Renci.SshNet.Connection internal class SshIdentification { /// - /// Initializes a new instance with the specified protocol version + /// Initializes a new instance of the class with the specified protocol version /// and software version. /// /// The SSH protocol version. - /// The software version of the implementation + /// The software version of the implementation. /// is . /// is . public SshIdentification(string protocolVersion, string softwareVersion) - : this(protocolVersion, softwareVersion, null) + : this(protocolVersion, softwareVersion, comments: null) { } /// - /// Initializes a new instance with the specified protocol version, + /// Initializes a new instance of the class with the specified protocol version, /// software version and comments. /// /// The SSH protocol version. - /// The software version of the implementation + /// The software version of the implementation. /// The comments. /// is . /// is . public SshIdentification(string protocolVersion, string softwareVersion, string comments) { if (protocolVersion == null) - throw new ArgumentNullException("protocolVersion"); + { + throw new ArgumentNullException(nameof(protocolVersion)); + } + if (softwareVersion == null) - throw new ArgumentNullException("softwareVersion"); + { + throw new ArgumentNullException(nameof(softwareVersion)); + } ProtocolVersion = protocolVersion; SoftwareVersion = softwareVersion; @@ -42,7 +47,7 @@ public SshIdentification(string protocolVersion, string softwareVersion, string } /// - /// Gets or sets the software version of the implementation. + /// Gets the software version of the implementation. /// /// /// The software version of the implementation. @@ -51,18 +56,18 @@ public SshIdentification(string protocolVersion, string softwareVersion, string /// This is primarily used to trigger compatibility extensions and to indicate /// the capabilities of an implementation. /// - public string SoftwareVersion { get; private set; } + public string SoftwareVersion { get; } /// - /// Gets or sets the SSH protocol version. + /// Gets the SSH protocol version. /// /// /// The SSH protocol version. /// - public string ProtocolVersion { get; private set; } + public string ProtocolVersion { get; } /// - /// Gets or sets the comments. + /// Gets the comments. /// /// /// The comments, or if there are no comments. @@ -71,7 +76,7 @@ public SshIdentification(string protocolVersion, string softwareVersion, string /// should contain additional information that might be useful /// in solving user problems. /// - public string Comments { get; private set; } + public string Comments { get; } /// /// Returns the SSH identification string. @@ -82,10 +87,12 @@ public SshIdentification(string protocolVersion, string softwareVersion, string public override string ToString() { var identificationString = "SSH-" + ProtocolVersion + "-" + SoftwareVersion; + if (Comments != null) { identificationString += " " + Comments; } + return identificationString; } } diff --git a/src/Renci.SshNet/ConnectionInfo.cs b/src/Renci.SshNet/ConnectionInfo.cs index f0f8b57c7..b36b4eb15 100644 --- a/src/Renci.SshNet/ConnectionInfo.cs +++ b/src/Renci.SshNet/ConnectionInfo.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net; using System.Text; + using Renci.SshNet.Abstractions; -using Renci.SshNet.Security; -using Renci.SshNet.Messages.Connection; using Renci.SshNet.Common; using Renci.SshNet.Messages.Authentication; -using Renci.SshNet.Security.Cryptography.Ciphers.Modes; +using Renci.SshNet.Messages.Connection; +using Renci.SshNet.Security; using Renci.SshNet.Security.Cryptography.Ciphers; +using Renci.SshNet.Security.Cryptography.Ciphers.Modes; namespace Renci.SshNet { @@ -161,7 +163,7 @@ public class ConnectionInfo : IConnectionInfoInternal /// Gets or sets the character encoding. /// /// - /// The character encoding. The default is . + /// The character encoding. The default is . /// public Encoding Encoding { get; set; } @@ -232,7 +234,7 @@ public class ConnectionInfo : IConnectionInfoInternal public string ServerVersion { get; internal set; } /// - /// Get the client version. + /// Gets the client version. /// public string ClientVersion { get; internal set; } @@ -253,7 +255,7 @@ public class ConnectionInfo : IConnectionInfoInternal /// is null. /// No specified. public ConnectionInfo(string host, string username, params AuthenticationMethod[] authenticationMethods) - : this(host, DefaultPort, username, ProxyTypes.None, null, 0, null, null, authenticationMethods) + : this(host, DefaultPort, username, ProxyTypes.None, proxyHost: null, 0, proxyUsername: null, proxyPassword: null, authenticationMethods) { } @@ -266,11 +268,11 @@ public ConnectionInfo(string host, string username, params AuthenticationMethod[ /// The authentication methods. /// is null. /// is null, a zero-length string or contains only whitespace characters. - /// is not within and . + /// is not within and . /// is null. /// No specified. public ConnectionInfo(string host, int port, string username, params AuthenticationMethod[] authenticationMethods) - : this(host, port, username, ProxyTypes.None, null, 0, null, null, authenticationMethods) + : this(host, port, username, ProxyTypes.None, proxyHost: null, 0, proxyUsername: null, proxyPassword: null, authenticationMethods) { } @@ -288,35 +290,51 @@ public ConnectionInfo(string host, int port, string username, params Authenticat /// The authentication methods. /// is null. /// is null, a zero-length string or contains only whitespace characters. - /// is not within and . + /// is not within and . /// is not and is null. - /// is not and is not within and . + /// is not and is not within and . /// is null. /// No specified. public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods) { if (host == null) - throw new ArgumentNullException("host"); + { + throw new ArgumentNullException(nameof(host)); + } + port.ValidatePort("port"); if (username == null) - throw new ArgumentNullException("username"); + { + throw new ArgumentNullException(nameof(username)); + } + if (username.All(char.IsWhiteSpace)) - throw new ArgumentException("Cannot be empty or contain only whitespace.", "username"); + { + throw new ArgumentException("Cannot be empty or contain only whitespace.", nameof(username)); + } if (proxyType != ProxyTypes.None) { if (proxyHost == null) - throw new ArgumentNullException("proxyHost"); + { + throw new ArgumentNullException(nameof(proxyHost)); + } + proxyPort.ValidatePort("proxyPort"); } if (authenticationMethods == null) - throw new ArgumentNullException("authenticationMethods"); + { + throw new ArgumentNullException(nameof(authenticationMethods)); + } + if (authenticationMethods.Length == 0) - throw new ArgumentException("At least one authentication method should be specified.", "authenticationMethods"); + { + throw new ArgumentException("At least one authentication method should be specified.", nameof(authenticationMethods)); + } - // Set default connection values + // Set default connection values Timeout = DefaultTimeout; ChannelCloseTimeout = DefaultChannelCloseTimeout; RetryAttempts = 10; @@ -325,98 +343,83 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy KeyExchangeAlgorithms = new Dictionary { - {"curve25519-sha256", typeof(KeyExchangeECCurve25519)}, - {"curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519)}, - {"ecdh-sha2-nistp256", typeof(KeyExchangeECDH256)}, - {"ecdh-sha2-nistp384", typeof(KeyExchangeECDH384)}, - {"ecdh-sha2-nistp521", typeof(KeyExchangeECDH521)}, - {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)}, - {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)}, - {"diffie-hellman-group16-sha512", typeof(KeyExchangeDiffieHellmanGroup16Sha512)}, - {"diffie-hellman-group14-sha256", typeof (KeyExchangeDiffieHellmanGroup14Sha256)}, - {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)}, - {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)}, + { "curve25519-sha256", typeof(KeyExchangeECCurve25519) }, + { "curve25519-sha256@libssh.org", typeof(KeyExchangeECCurve25519) }, + { "ecdh-sha2-nistp256", typeof(KeyExchangeECDH256) }, + { "ecdh-sha2-nistp384", typeof(KeyExchangeECDH384) }, + { "ecdh-sha2-nistp521", typeof(KeyExchangeECDH521) }, + { "diffie-hellman-group-exchange-sha256", typeof(KeyExchangeDiffieHellmanGroupExchangeSha256) }, + { "diffie-hellman-group-exchange-sha1", typeof(KeyExchangeDiffieHellmanGroupExchangeSha1) }, + { "diffie-hellman-group16-sha512", typeof(KeyExchangeDiffieHellmanGroup16Sha512) }, + { "diffie-hellman-group14-sha256", typeof(KeyExchangeDiffieHellmanGroup14Sha256) }, + { "diffie-hellman-group14-sha1", typeof(KeyExchangeDiffieHellmanGroup14Sha1) }, + { "diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellmanGroup1Sha1) }, }; Encryptions = new Dictionary { - {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, - {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))}, - {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, - {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, - {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, - {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))}, - {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, - {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, - {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, - {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, - ////{"serpent256-cbc", typeof(CipherSerpent256CBC)}, - ////{"serpent192-cbc", typeof(...)}, - ////{"serpent128-cbc", typeof(...)}, - {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))}, - {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))}, - {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))}, - ////{"idea-cbc", typeof(...)}, - {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))}, - ////{"rijndael-cbc@lysator.liu.se", typeof(...)}, - {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, - {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, + { "aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), padding: null)) }, + { "3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, dischargeFirstBytes: false)) }, + { "arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, dischargeFirstBytes: true)) }, + { "arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, dischargeFirstBytes: true)) }, + { "cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), padding: null)) }, + { "aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), padding: null)) }, + { "aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), padding: null)) }, }; HmacAlgorithms = new Dictionary { - {"hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)}, - {"hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))}, - {"hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)}, - {"hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))}, - {"hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)}, - {"hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))}, - {"hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)}, - {"hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))}, - //{"umac-64@openssh.com", typeof(HMacSha1)}, - {"hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, - {"hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, - //{"none", typeof(...)}, + { "hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5) }, + { "hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96)) }, + { "hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1) }, + { "hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96)) }, + { "hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256) }, + { "hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96)) }, + { "hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512) }, + { "hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96)) }, + { "hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160) }, + { "hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160) }, }; HostKeyAlgorithms = new Dictionary> { - {"ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data)}, - {"ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data)}, - {"ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data)}, - {"ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data)}, - {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)}, - {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)}, - //{"x509v3-sign-rsa", () => { ... }, - //{"x509v3-sign-dss", () => { ... }, - //{"spki-sign-rsa", () => { ... }, - //{"spki-sign-dss", () => { ... }, - //{"pgp-sign-rsa", () => { ... }, - //{"pgp-sign-dss", () => { ... }, + { "ssh-ed25519", data => new KeyHostAlgorithm("ssh-ed25519", new ED25519Key(), data) }, + { "ecdsa-sha2-nistp256", data => new KeyHostAlgorithm("ecdsa-sha2-nistp256", new EcdsaKey(), data) }, + { "ecdsa-sha2-nistp384", data => new KeyHostAlgorithm("ecdsa-sha2-nistp384", new EcdsaKey(), data) }, + { "ecdsa-sha2-nistp521", data => new KeyHostAlgorithm("ecdsa-sha2-nistp521", new EcdsaKey(), data) }, + { "ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data) }, + { "ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data) }, }; CompressionAlgorithms = new Dictionary { - //{"zlib@openssh.com", typeof(ZlibOpenSsh)}, - //{"zlib", typeof(Zlib)}, - {"none", null}, + { "none", null }, }; ChannelRequests = new Dictionary { - {EnvironmentVariableRequestInfo.Name, new EnvironmentVariableRequestInfo()}, - {ExecRequestInfo.Name, new ExecRequestInfo()}, - {ExitSignalRequestInfo.Name, new ExitSignalRequestInfo()}, - {ExitStatusRequestInfo.Name, new ExitStatusRequestInfo()}, - {PseudoTerminalRequestInfo.Name, new PseudoTerminalRequestInfo()}, - {ShellRequestInfo.Name, new ShellRequestInfo()}, - {SignalRequestInfo.Name, new SignalRequestInfo()}, - {SubsystemRequestInfo.Name, new SubsystemRequestInfo()}, - {WindowChangeRequestInfo.Name, new WindowChangeRequestInfo()}, - {X11ForwardingRequestInfo.Name, new X11ForwardingRequestInfo()}, - {XonXoffRequestInfo.Name, new XonXoffRequestInfo()}, - {EndOfWriteRequestInfo.Name, new EndOfWriteRequestInfo()}, - {KeepAliveRequestInfo.Name, new KeepAliveRequestInfo()}, + { EnvironmentVariableRequestInfo.Name, new EnvironmentVariableRequestInfo() }, + { ExecRequestInfo.Name, new ExecRequestInfo() }, + { ExitSignalRequestInfo.Name, new ExitSignalRequestInfo() }, + { ExitStatusRequestInfo.Name, new ExitStatusRequestInfo() }, + { PseudoTerminalRequestInfo.Name, new PseudoTerminalRequestInfo() }, + { ShellRequestInfo.Name, new ShellRequestInfo() }, + { SignalRequestInfo.Name, new SignalRequestInfo() }, + { SubsystemRequestInfo.Name, new SubsystemRequestInfo() }, + { WindowChangeRequestInfo.Name, new WindowChangeRequestInfo() }, + { X11ForwardingRequestInfo.Name, new X11ForwardingRequestInfo() }, + { XonXoffRequestInfo.Name, new XonXoffRequestInfo() }, + { EndOfWriteRequestInfo.Name, new EndOfWriteRequestInfo() }, + { KeepAliveRequestInfo.Name, new KeepAliveRequestInfo() }, }; Host = host; @@ -443,7 +446,9 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy internal void Authenticate(ISession session, IServiceFactory serviceFactory) { if (serviceFactory == null) - throw new ArgumentNullException("serviceFactory"); + { + throw new ArgumentNullException(nameof(serviceFactory)); + } IsAuthenticated = false; var clientAuthentication = serviceFactory.CreateClientAuthentication(); @@ -455,15 +460,10 @@ internal void Authenticate(ISession session, IServiceFactory serviceFactory) /// Signals that an authentication banner message was received from the server. /// /// The session in which the banner message was received. - /// The banner message.{ + /// The banner message. void IConnectionInfoInternal.UserAuthenticationBannerReceived(object sender, MessageEventArgs e) { - var authenticationBanner = AuthenticationBanner; - if (authenticationBanner != null) - { - authenticationBanner(this, - new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language)); - } + AuthenticationBanner?.Invoke(this, new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language)); } IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod() diff --git a/src/Renci.SshNet/ExpectAction.cs b/src/Renci.SshNet/ExpectAction.cs index c2ff3a6a1..4a52c889d 100644 --- a/src/Renci.SshNet/ExpectAction.cs +++ b/src/Renci.SshNet/ExpectAction.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet { /// - /// Specifies behavior for expected expression + /// Specifies behavior for expected expression. /// public class ExpectAction { @@ -27,10 +27,14 @@ public class ExpectAction public ExpectAction(Regex expect, Action action) { if (expect == null) - throw new ArgumentNullException("expect"); + { + throw new ArgumentNullException(nameof(expect)); + } if (action == null) - throw new ArgumentNullException("action"); + { + throw new ArgumentNullException(nameof(action)); + } Expect = expect; Action = action; @@ -45,10 +49,14 @@ public ExpectAction(Regex expect, Action action) public ExpectAction(string expect, Action action) { if (expect == null) - throw new ArgumentNullException("expect"); + { + throw new ArgumentNullException(nameof(expect)); + } if (action == null) - throw new ArgumentNullException("action"); + { + throw new ArgumentNullException(nameof(action)); + } Expect = new Regex(Regex.Escape(expect)); Action = action; diff --git a/src/Renci.SshNet/ExpectAsyncResult.cs b/src/Renci.SshNet/ExpectAsyncResult.cs index 0f911c0b8..f83d32f75 100644 --- a/src/Renci.SshNet/ExpectAsyncResult.cs +++ b/src/Renci.SshNet/ExpectAsyncResult.cs @@ -1,10 +1,11 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet { /// - /// Provides additional information for asynchronous command execution + /// Provides additional information for asynchronous command execution. /// public class ExpectAsyncResult : AsyncResult { @@ -13,7 +14,7 @@ public class ExpectAsyncResult : AsyncResult /// /// The async callback. /// The state. - internal ExpectAsyncResult(AsyncCallback asyncCallback, Object state) + internal ExpectAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) { } diff --git a/src/Renci.SshNet/ForwardedPort.cs b/src/Renci.SshNet/ForwardedPort.cs index 26baaa1db..deca52423 100644 --- a/src/Renci.SshNet/ForwardedPort.cs +++ b/src/Renci.SshNet/ForwardedPort.cs @@ -56,11 +56,19 @@ public virtual void Start() CheckDisposed(); if (IsStarted) + { throw new InvalidOperationException("Forwarded port is already started."); + } + if (Session == null) + { throw new InvalidOperationException("Forwarded port is not added to a client."); + } + if (!Session.IsConnected) + { throw new SshConnectionException("Client not connected."); + } Session.ErrorOccured += Session_ErrorOccured; StartPort(); @@ -127,11 +135,7 @@ protected virtual void Dispose(bool disposing) /// The exception. protected void RaiseExceptionEvent(Exception exception) { - var handlers = Exception; - if (handlers != null) - { - handlers(this, new ExceptionEventArgs(exception)); - } + Exception?.Invoke(this, new ExceptionEventArgs(exception)); } /// @@ -141,11 +145,7 @@ protected void RaiseExceptionEvent(Exception exception) /// Request originator port. protected void RaiseRequestReceived(string host, uint port) { - var handlers = RequestReceived; - if (handlers != null) - { - handlers(this, new PortForwardEventArgs(host, port)); - } + RequestReceived?.Invoke(this, new PortForwardEventArgs(host, port)); } /// @@ -153,11 +153,7 @@ protected void RaiseRequestReceived(string host, uint port) /// private void RaiseClosing() { - var handlers = Closing; - if (handlers != null) - { - handlers(this, EventArgs.Empty); - } + Closing?.Invoke(this, EventArgs.Empty); } /// diff --git a/src/Renci.SshNet/ForwardedPortDynamic.NET.cs b/src/Renci.SshNet/ForwardedPortDynamic.NET.cs index 31b3a0ab9..957483f71 100644 --- a/src/Renci.SshNet/ForwardedPortDynamic.NET.cs +++ b/src/Renci.SshNet/ForwardedPortDynamic.NET.cs @@ -1,9 +1,10 @@ using System; using System.Linq; -using System.Text; using System.Net; using System.Net.Sockets; +using System.Text; using System.Threading; + using Renci.SshNet.Abstractions; using Renci.SshNet.Channels; using Renci.SshNet.Common; @@ -78,7 +79,7 @@ private void StartAccept(SocketAsyncEventArgs e) private void AcceptCompleted(object sender, SocketAsyncEventArgs e) { - if (e.SocketError == SocketError.OperationAborted || e.SocketError == SocketError.NotSocket) + if (e.SocketError is SocketError.OperationAborted or SocketError.NotSocket) { // server was stopped return; @@ -91,6 +92,7 @@ private void AcceptCompleted(object sender, SocketAsyncEventArgs e) { // accept new connection StartAccept(e); + // dispose broken client socket CloseClientSocket(clientSocket); return; @@ -98,6 +100,7 @@ private void AcceptCompleted(object sender, SocketAsyncEventArgs e) // accept new connection StartAccept(e); + // process connection ProcessAccept(clientSocket); } @@ -146,7 +149,7 @@ private void ProcessAccept(Socket clientSocket) // the CountdownEvent will be disposed try { - pendingChannelCountdown.Signal(); + _ = pendingChannelCountdown.Signal(); } catch (ObjectDisposedException) { @@ -170,10 +173,7 @@ private void ProcessAccept(Socket clientSocket) private void InitializePendingChannelCountdown() { var original = Interlocked.Exchange(ref _pendingChannelCountdown, new CountdownEvent(1)); - if (original != null) - { - original.Dispose(); - } + original?.Dispose(); } private bool HandleSocks(IChannelDirectTcpip channel, Socket clientSocket, TimeSpan timeout) @@ -251,11 +251,7 @@ private static void CloseClientSocket(Socket clientSocket) partial void StopListener() { // close listener socket - var listener = _listener; - if (listener != null) - { - listener.Dispose(); - } + _listener?.Dispose(); // unsubscribe from session events var session = Session; @@ -272,7 +268,8 @@ partial void StopListener() /// The maximum time to wait for the pending channels to close. partial void InternalStop(TimeSpan timeout) { - _pendingChannelCountdown.Signal(); + _ = _pendingChannelCountdown.Signal(); + if (!_pendingChannelCountdown.Wait(timeout)) { // TODO: log as warning @@ -401,12 +398,12 @@ private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan t { // no user authentication is one of the authentication methods supported // by the SOCKS client - SocketAbstraction.Send(socket, new byte[] {0x05, 0x00}, 0, 2); + SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2); } else { // the SOCKS client requires authentication, which we currently do not support - SocketAbstraction.Send(socket, new byte[] {0x05, 0xFF}, 0, 2); + SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2); // we continue business as usual but expect the client to close the connection // so one of the subsequent reads should return -1 signaling that the client @@ -592,11 +589,10 @@ private static string ReadString(Socket socket, TimeSpan timeout) break; } - var c = (char) byteRead; - text.Append(c); + _ = text.Append((char) byteRead); } + return text.ToString(); } } } - diff --git a/src/Renci.SshNet/ForwardedPortDynamic.cs b/src/Renci.SshNet/ForwardedPortDynamic.cs index dbe9794db..1331557a8 100644 --- a/src/Renci.SshNet/ForwardedPortDynamic.cs +++ b/src/Renci.SshNet/ForwardedPortDynamic.cs @@ -10,15 +10,23 @@ public partial class ForwardedPortDynamic : ForwardedPort { private ForwardedPortStatus _status; + /// + /// Holds a value indicating whether the current instance is disposed. + /// + /// + /// true if the current instance is disposed; otherwise, false. + /// + private bool _isDisposed; + /// /// Gets the bound host. /// - public string BoundHost { get; private set; } + public string BoundHost { get; } /// /// Gets the bound port. /// - public uint BoundPort { get; private set; } + public uint BoundPort { get; } /// /// Gets a value indicating whether port forwarding is started. @@ -35,7 +43,8 @@ public override bool IsStarted /// Initializes a new instance of the class. /// /// The port. - public ForwardedPortDynamic(uint port) : this(string.Empty, port) + public ForwardedPortDynamic(uint port) + : this(string.Empty, port) { } @@ -57,7 +66,9 @@ public ForwardedPortDynamic(string host, uint port) protected override void StartPort() { if (!ForwardedPortStatus.ToStarting(ref _status)) + { return; + } try { @@ -78,14 +89,19 @@ protected override void StartPort() protected override void StopPort(TimeSpan timeout) { if (!ForwardedPortStatus.ToStopping(ref _status)) + { return; + } // signal existing channels that the port is closing base.StopPort(timeout); + // prevent new requests from getting processed StopListener(); + // wait for open channels to close InternalStop(timeout); + // mark port stopped _status = ForwardedPortStatus.Stopped; } @@ -97,7 +113,9 @@ protected override void StopPort(TimeSpan timeout) protected override void CheckDisposed() { if (_isDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } } partial void InternalStart(); @@ -113,51 +131,40 @@ protected override void CheckDisposed() /// The maximum time to wait for the forwarded port to stop. partial void InternalStop(TimeSpan timeout); - #region IDisposable Members - - /// - /// Holds a value indicating whether the current instance is disposed. - /// - /// - /// true if the current instance is disposed; otherwise, false. - /// - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } partial void InternalDispose(bool disposing); /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (_isDisposed) + { return; + } base.Dispose(disposing); - InternalDispose(disposing); + InternalDispose(disposing); _isDisposed = true; } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~ForwardedPortDynamic() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/ForwardedPortLocal.NET.cs b/src/Renci.SshNet/ForwardedPortLocal.NET.cs index ba01ddbd3..60777b97a 100644 --- a/src/Renci.SshNet/ForwardedPortLocal.NET.cs +++ b/src/Renci.SshNet/ForwardedPortLocal.NET.cs @@ -1,7 +1,8 @@ using System; -using System.Net.Sockets; using System.Net; +using System.Net.Sockets; using System.Threading; + using Renci.SshNet.Abstractions; using Renci.SshNet.Common; @@ -73,7 +74,7 @@ private void StartAccept(SocketAsyncEventArgs e) private void AcceptCompleted(object sender, SocketAsyncEventArgs e) { - if (e.SocketError == SocketError.OperationAborted || e.SocketError == SocketError.NotSocket) + if (e.SocketError is SocketError.OperationAborted or SocketError.NotSocket) { // server was stopped return; @@ -86,6 +87,7 @@ private void AcceptCompleted(object sender, SocketAsyncEventArgs e) { // accept new connection StartAccept(e); + // dispose broken client socket CloseClientSocket(clientSocket); return; @@ -93,6 +95,7 @@ private void AcceptCompleted(object sender, SocketAsyncEventArgs e) // accept new connection StartAccept(e); + // process connection ProcessAccept(clientSocket); } @@ -139,7 +142,7 @@ private void ProcessAccept(Socket clientSocket) // the CountdownEvent will be disposed try { - pendingChannelCountdown.Signal(); + _ = pendingChannelCountdown.Signal(); } catch (ObjectDisposedException) { @@ -163,10 +166,7 @@ private void ProcessAccept(Socket clientSocket) private void InitializePendingChannelCountdown() { var original = Interlocked.Exchange(ref _pendingChannelCountdown, new CountdownEvent(1)); - if (original != null) - { - original.Dispose(); - } + original?.Dispose(); } private static void CloseClientSocket(Socket clientSocket) @@ -192,11 +192,7 @@ private static void CloseClientSocket(Socket clientSocket) partial void StopListener() { // close listener socket - var listener = _listener; - if (listener != null) - { - listener.Dispose(); - } + _listener?.Dispose(); // unsubscribe from session events var session = Session; @@ -213,7 +209,8 @@ partial void StopListener() /// The maximum time to wait for the pending channels to close. partial void InternalStop(TimeSpan timeout) { - _pendingChannelCountdown.Signal(); + _ = _pendingChannelCountdown.Signal(); + if (!_pendingChannelCountdown.Wait(timeout)) { // TODO: log as warning diff --git a/src/Renci.SshNet/ForwardedPortLocal.cs b/src/Renci.SshNet/ForwardedPortLocal.cs index 79246bd73..fe3215de2 100644 --- a/src/Renci.SshNet/ForwardedPortLocal.cs +++ b/src/Renci.SshNet/ForwardedPortLocal.cs @@ -1,14 +1,17 @@ using System; +using System.Net; + using Renci.SshNet.Common; namespace Renci.SshNet { /// - /// Provides functionality for local port forwarding + /// Provides functionality for local port forwarding. /// public partial class ForwardedPortLocal : ForwardedPort, IDisposable { private ForwardedPortStatus _status; + private bool _isDisposed; /// /// Gets the bound host. @@ -47,9 +50,9 @@ public override bool IsStarted /// The bound port. /// The host. /// The port. - /// is greater than . + /// is greater than . /// is null. - /// is greater than . + /// is greater than . /// /// /// @@ -66,9 +69,9 @@ public ForwardedPortLocal(uint boundPort, string host, uint port) /// The port. /// is null. /// is null. - /// is greater than . + /// is greater than . public ForwardedPortLocal(string boundHost, string host, uint port) - : this(boundHost, 0, host, port) + : this(boundHost, 0, host, port) { } @@ -81,15 +84,19 @@ public ForwardedPortLocal(string boundHost, string host, uint port) /// The port. /// is null. /// is null. - /// is greater than . - /// is greater than . + /// is greater than . + /// is greater than . public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint port) { if (boundHost == null) - throw new ArgumentNullException("boundHost"); + { + throw new ArgumentNullException(nameof(boundHost)); + } if (host == null) - throw new ArgumentNullException("host"); + { + throw new ArgumentNullException(nameof(host)); + } boundPort.ValidatePort("boundPort"); port.ValidatePort("port"); @@ -107,7 +114,9 @@ public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint po protected override void StartPort() { if (!ForwardedPortStatus.ToStarting(ref _status)) + { return; + } try { @@ -128,14 +137,19 @@ protected override void StartPort() protected override void StopPort(TimeSpan timeout) { if (!ForwardedPortStatus.ToStopping(ref _status)) + { return; + } // signal existing channels that the port is closing base.StopPort(timeout); + // prevent new requests from getting processed StopListener(); + // wait for open channels to close InternalStop(timeout); + // mark port stopped _status = ForwardedPortStatus.Stopped; } @@ -147,7 +161,9 @@ protected override void StopPort(TimeSpan timeout) protected override void CheckDisposed() { if (_isDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } } partial void InternalStart(); @@ -162,45 +178,40 @@ protected override void CheckDisposed() partial void InternalStop(TimeSpan timeout); - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } partial void InternalDispose(bool disposing); /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (_isDisposed) + { return; + } base.Dispose(disposing); - InternalDispose(disposing); + InternalDispose(disposing); _isDisposed = true; } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~ForwardedPortLocal() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/ForwardedPortRemote.cs b/src/Renci.SshNet/ForwardedPortRemote.cs index b2ed15fe4..6405f13a1 100644 --- a/src/Renci.SshNet/ForwardedPortRemote.cs +++ b/src/Renci.SshNet/ForwardedPortRemote.cs @@ -1,23 +1,24 @@ using System; -using System.Threading; -using Renci.SshNet.Messages.Connection; -using Renci.SshNet.Common; using System.Globalization; using System.Net; +using System.Threading; + using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; +using Renci.SshNet.Messages.Connection; namespace Renci.SshNet { /// - /// Provides functionality for remote port forwarding + /// Provides functionality for remote port forwarding. /// public class ForwardedPortRemote : ForwardedPort, IDisposable { private ForwardedPortStatus _status; private bool _requestStatus; - private EventWaitHandle _globalRequestResponse = new AutoResetEvent(false); private CountdownEvent _pendingChannelCountdown; + private bool _isDisposed; /// /// Gets a value indicating whether port forwarding is started. @@ -81,14 +82,19 @@ public string Host /// The port. /// is null. /// is null. - /// is greater than . - /// is greater than . + /// is greater than . + /// is greater than . public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress hostAddress, uint port) { if (boundHostAddress == null) - throw new ArgumentNullException("boundHostAddress"); + { + throw new ArgumentNullException(nameof(boundHostAddress)); + } + if (hostAddress == null) - throw new ArgumentNullException("hostAddress"); + { + throw new ArgumentNullException(nameof(hostAddress)); + } boundPort.ValidatePort("boundPort"); port.ValidatePort("port"); @@ -135,7 +141,9 @@ public ForwardedPortRemote(string boundHost, uint boundPort, string host, uint p protected override void StartPort() { if (!ForwardedPortStatus.ToStarting(ref _status)) + { return; + } InitializePendingChannelCountdown(); @@ -151,6 +159,7 @@ protected override void StartPort() // send global request to start forwarding Session.SendMessage(new TcpIpForwardGlobalRequestMessage(BoundHost, BoundPort)); + // wat for response on global request to start direct tcpip Session.WaitOnHandle(_globalRequestResponse); @@ -183,15 +192,18 @@ protected override void StartPort() protected override void StopPort(TimeSpan timeout) { if (!ForwardedPortStatus.ToStopping(ref _status)) + { return; + } base.StopPort(timeout); // send global request to cancel direct tcpip Session.SendMessage(new CancelTcpIpForwardGlobalRequestMessage(BoundHost, BoundPort)); + // wait for response on global request to cancel direct tcpip or completion of message // listener loop (in which case response on global request can never be received) - WaitHandle.WaitAny(new[] { _globalRequestResponse, Session.MessageListenerCompleted }, timeout); + _ = WaitHandle.WaitAny(new[] { _globalRequestResponse, Session.MessageListenerCompleted }, timeout); // unsubscribe from session events as either the tcpip forward is cancelled at the // server, or our session message loop has completed @@ -200,8 +212,8 @@ protected override void StopPort(TimeSpan timeout) Session.ChannelOpenReceived -= Session_ChannelOpening; // wait for pending channels to close - _pendingChannelCountdown.Signal(); - + _ = _pendingChannelCountdown.Signal(); + if (!_pendingChannelCountdown.Wait(timeout)) { // TODO: log as warning @@ -218,21 +230,24 @@ protected override void StopPort(TimeSpan timeout) protected override void CheckDisposed() { if (_isDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } } private void Session_ChannelOpening(object sender, MessageEventArgs e) { var channelOpenMessage = e.Message; - var info = channelOpenMessage.Info as ForwardedTcpipChannelInfo; - if (info != null) + if (channelOpenMessage.Info is ForwardedTcpipChannelInfo info) { - // Ensure this is the corresponding request + // Ensure this is the corresponding request if (info.ConnectedAddress == BoundHost && info.ConnectedPort == BoundPort) { if (!IsStarted) { - Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, "", ChannelOpenFailureMessage.AdministrativelyProhibited)); + Session.SendMessage(new ChannelOpenFailureMessage(channelOpenMessage.LocalChannelNumber, + string.Empty, + ChannelOpenFailureMessage.AdministrativelyProhibited)); return; } @@ -266,7 +281,7 @@ private void Session_ChannelOpening(object sender, MessageEventArgs e) { _requestStatus = true; + if (BoundPort == 0) { BoundPort = (e.Message.BoundPort == null) ? 0 : e.Message.BoundPort.Value; } - _globalRequestResponse.Set(); + _ = _globalRequestResponse.Set(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -341,7 +350,9 @@ public void Dispose() protected override void Dispose(bool disposing) { if (_isDisposed) + { return; + } base.Dispose(disposing); @@ -375,14 +386,11 @@ protected override void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~ForwardedPortRemote() { Dispose(false); } - - #endregion } } diff --git a/src/Renci.SshNet/ForwardedPortStatus.cs b/src/Renci.SshNet/ForwardedPortStatus.cs index 7fce9ee7e..133c6d5f7 100644 --- a/src/Renci.SshNet/ForwardedPortStatus.cs +++ b/src/Renci.SshNet/ForwardedPortStatus.cs @@ -5,14 +5,14 @@ namespace Renci.SshNet { internal class ForwardedPortStatus { - private readonly int _value; - private readonly string _name; - public static readonly ForwardedPortStatus Stopped = new ForwardedPortStatus(1, "Stopped"); public static readonly ForwardedPortStatus Stopping = new ForwardedPortStatus(2, "Stopping"); public static readonly ForwardedPortStatus Started = new ForwardedPortStatus(3, "Started"); public static readonly ForwardedPortStatus Starting = new ForwardedPortStatus(4, "Starting"); + private readonly int _value; + private readonly string _name; + private ForwardedPortStatus(int value, string name) { _value = value; @@ -21,15 +21,21 @@ private ForwardedPortStatus(int value, string name) public override bool Equals(object other) { - if (ReferenceEquals(other, null)) + if (other is null) + { return false; + } if (ReferenceEquals(this, other)) + { return true; + } var forwardedPortStatus = other as ForwardedPortStatus; if (forwardedPortStatus == null) + { return false; + } return forwardedPortStatus._value == _value; } @@ -37,10 +43,10 @@ public override bool Equals(object other) public static bool operator ==(ForwardedPortStatus left, ForwardedPortStatus right) { // check if lhs is null - if (ReferenceEquals(left, null)) + if (left is null) { // check if both lhs and rhs are null - return (ReferenceEquals(right, null)); + return right is null; } return left.Equals(right); @@ -85,7 +91,9 @@ public static bool ToStopping(ref ForwardedPortStatus status) // we've successfully transitioned from Started to Stopping if (status == Stopping) + { return true; + } // attempt to transition from Starting to Stopping previousStatus = Interlocked.CompareExchange(ref status, Stopping, Starting); @@ -97,7 +105,9 @@ public static bool ToStopping(ref ForwardedPortStatus status) // we've successfully transitioned from Starting to Stopping if (status == Stopping) + { return true; + } // there's no valid transition from status to Stopping throw new InvalidOperationException(string.Format("Forwarded port cannot transition from '{0}' to '{1}'.", @@ -129,7 +139,9 @@ public static bool ToStarting(ref ForwardedPortStatus status) // we've successfully transitioned from Stopped to Starting if (status == Starting) + { return true; + } // there's no valid transition from status to Starting throw new InvalidOperationException(string.Format("Forwarded port cannot transition from '{0}' to '{1}'.", diff --git a/src/Renci.SshNet/IBaseClient.cs b/src/Renci.SshNet/IBaseClient.cs index c11adb4f6..56828f9b4 100644 --- a/src/Renci.SshNet/IBaseClient.cs +++ b/src/Renci.SshNet/IBaseClient.cs @@ -1,9 +1,10 @@ -using Renci.SshNet.Common; -using System; +using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using Renci.SshNet.Common; + namespace Renci.SshNet { /// @@ -101,4 +102,4 @@ public interface IBaseClient /// The method was called after the client was disposed. void SendKeepAlive(); } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/IConnectionInfo.cs b/src/Renci.SshNet/IConnectionInfo.cs index 22abefda2..77908d2d7 100644 --- a/src/Renci.SshNet/IConnectionInfo.cs +++ b/src/Renci.SshNet/IConnectionInfo.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; + using Renci.SshNet.Common; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages.Connection; @@ -13,7 +14,7 @@ internal interface IConnectionInfoInternal : IConnectionInfo /// Signals that an authentication banner message was received from the server. /// /// The session in which the banner message was received. - /// The banner message.{ + /// The banner message. void UserAuthenticationBannerReceived(object sender, MessageEventArgs e); /// @@ -41,7 +42,7 @@ internal interface IConnectionInfoInternal : IConnectionInfo internal interface IConnectionInfo { /// - /// Gets or sets the timeout to used when waiting for a server to acknowledge closing a channel. + /// Gets the timeout to used when waiting for a server to acknowledge closing a channel. /// /// /// The channel close timeout. The default value is 1 second. @@ -121,7 +122,7 @@ internal interface IConnectionInfo int RetryAttempts { get; } /// - /// Gets or sets connection timeout. + /// Gets the connection timeout. /// /// /// The connection timeout. The default value is 30 seconds. diff --git a/src/Renci.SshNet/IRemotePathTransformation.cs b/src/Renci.SshNet/IRemotePathTransformation.cs index 30c52421c..d139db5db 100644 --- a/src/Renci.SshNet/IRemotePathTransformation.cs +++ b/src/Renci.SshNet/IRemotePathTransformation.cs @@ -14,6 +14,4 @@ public interface IRemotePathTransformation /// string Transform(string path); } - - } diff --git a/src/Renci.SshNet/IServiceFactory.cs b/src/Renci.SshNet/IServiceFactory.cs index dad93e237..cb20ae064 100644 --- a/src/Renci.SshNet/IServiceFactory.cs +++ b/src/Renci.SshNet/IServiceFactory.cs @@ -75,10 +75,10 @@ internal partial interface IServiceFactory /// The TERM environment variable. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. - /// Size of the buffer. /// The terminal mode values. + /// Size of the buffer. /// /// The created instance. /// diff --git a/src/Renci.SshNet/ISession.cs b/src/Renci.SshNet/ISession.cs index bc123c776..bc0239b07 100644 --- a/src/Renci.SshNet/ISession.cs +++ b/src/Renci.SshNet/ISession.cs @@ -1,12 +1,13 @@ using System; using System.Net.Sockets; using System.Threading; +using System.Threading.Tasks; + using Renci.SshNet.Channels; using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages.Connection; -using System.Threading.Tasks; namespace Renci.SshNet { diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs index 99e1e7b06..82117295c 100644 --- a/src/Renci.SshNet/ISftpClient.cs +++ b/src/Renci.SshNet/ISftpClient.cs @@ -2,11 +2,12 @@ using System.Collections.Generic; using System.IO; using System.Text; -using Renci.SshNet.Sftp; -using Renci.SshNet.Common; using System.Threading; using System.Threading.Tasks; +using Renci.SshNet.Common; +using Renci.SshNet.Sftp; + namespace Renci.SshNet { /// @@ -55,7 +56,7 @@ public interface ISftpClient : IBaseClient, IDisposable /// one (-1) milliseconds, which indicates an infinite timeout period. /// /// The method was called after the client was disposed. - /// represents a value that is less than -1 or greater than milliseconds. + /// represents a value that is less than -1 or greater than milliseconds. TimeSpan OperationTimeout { get; set; } /// @@ -1138,4 +1139,4 @@ public interface ISftpClient : IBaseClient, IDisposable /// void WriteAllText(string path, string contents, Encoding encoding); } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs index f8c78cbf5..90fc1f283 100644 --- a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs +++ b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs @@ -1,10 +1,11 @@ using System; using System.Linq; using System.Threading; + using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; -using Renci.SshNet.Common; namespace Renci.SshNet { @@ -13,16 +14,19 @@ namespace Renci.SshNet /// public class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod, IDisposable { + private readonly RequestMessage _requestMessage; private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; - private Session _session; private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false); private Exception _exception; - private readonly RequestMessage _requestMessage; + private bool _isDisposed; /// - /// Gets authentication method name + /// Gets the name of the authentication method. /// + /// + /// The name of the authentication method. + /// public override string Name { get { return _requestMessage.MethodName; } @@ -73,7 +77,9 @@ public override AuthenticationResult Authenticate(Session session) } if (_exception != null) + { throw _exception; + } return _authenticationResult; } @@ -81,20 +87,24 @@ public override AuthenticationResult Authenticate(Session session) private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e) { _authenticationResult = AuthenticationResult.Success; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e) { if (e.Message.PartialSuccess) + { _authenticationResult = AuthenticationResult.PartialSuccess; + } else + { _authenticationResult = AuthenticationResult.Failure; + } // Copy allowed authentication methods AllowedAuthentications = e.Message.AllowedAuthentications; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationInformationRequestReceived(object sender, MessageEventArgs e) @@ -110,10 +120,7 @@ private void Session_UserAuthenticationInformationRequestReceived(object sender, { try { - if (AuthenticationPrompt != null) - { - AuthenticationPrompt(this, eventArgs); - } + AuthenticationPrompt?.Invoke(this, eventArgs); var informationResponse = new InformationResponseMessage(); @@ -122,38 +129,36 @@ private void Session_UserAuthenticationInformationRequestReceived(object sender, informationResponse.Responses.Add(response); } - // Send information response message + // Send information response message _session.SendMessage(informationResponse); } catch (Exception exp) { _exception = exp; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } }); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -169,14 +174,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~KeyboardInteractiveAuthenticationMethod() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs b/src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs index d8780caa7..af2667842 100644 --- a/src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs +++ b/src/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs @@ -4,13 +4,15 @@ namespace Renci.SshNet { /// - /// Provides connection information when keyboard interactive authentication method is used + /// Provides connection information when keyboard interactive authentication method is used. /// /// /// /// public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable { + private bool _isDisposed; + /// /// Occurs when server prompts for more authentication information. /// @@ -19,8 +21,6 @@ public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable /// public event EventHandler AuthenticationPrompt; - // TODO: DOCS Add exception documentation for this class. - /// /// Initializes a new instance of the class. /// @@ -29,7 +29,6 @@ public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable public KeyboardInteractiveConnectionInfo(string host, string username) : this(host, DefaultPort, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty) { - } /// @@ -41,7 +40,6 @@ public KeyboardInteractiveConnectionInfo(string host, string username) public KeyboardInteractiveConnectionInfo(string host, int port, string username) : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty) { - } /// @@ -131,8 +129,7 @@ public KeyboardInteractiveConnectionInfo(string host, int port, string username, { foreach (var authenticationMethod in AuthenticationMethods) { - var kbdInteractive = authenticationMethod as KeyboardInteractiveAuthenticationMethod; - if (kbdInteractive != null) + if (authenticationMethod is KeyboardInteractiveAuthenticationMethod kbdInteractive) { kbdInteractive.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt; } @@ -142,34 +139,28 @@ public KeyboardInteractiveConnectionInfo(string host, int port, string username, private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e) { - if (AuthenticationPrompt != null) - { - AuthenticationPrompt(sender, e); - } + AuthenticationPrompt?.Invoke(sender, e); } - - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -177,8 +168,7 @@ protected virtual void Dispose(bool disposing) { foreach (var authenticationMethods in AuthenticationMethods) { - var disposable = authenticationMethods as IDisposable; - if (disposable != null) + if (authenticationMethods is IDisposable disposable) { disposable.Dispose(); } @@ -190,14 +180,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~KeyboardInteractiveConnectionInfo() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/MessageEventArgs.cs b/src/Renci.SshNet/MessageEventArgs.cs index 216b8adae..fead62e1e 100644 --- a/src/Renci.SshNet/MessageEventArgs.cs +++ b/src/Renci.SshNet/MessageEventArgs.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet /// /// Provides data for message events. /// - /// Message type + /// Message type. public class MessageEventArgs : EventArgs { /// @@ -14,14 +14,16 @@ public class MessageEventArgs : EventArgs public T Message { get; private set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The message. /// is null. public MessageEventArgs(T message) { if (message == null) - throw new ArgumentNullException("message"); + { + throw new ArgumentNullException(nameof(message)); + } Message = message; } diff --git a/src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs b/src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs index 5d5a22dce..ec9fd2047 100644 --- a/src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs +++ b/src/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs @@ -3,44 +3,44 @@ /// /// Represents "hostbased" SSH_MSG_USERAUTH_REQUEST message. /// - internal class RequestMessageHost : RequestMessage + internal sealed class RequestMessageHost : RequestMessage { /// /// Gets the public key algorithm for host key as ASCII encoded byte array. /// - public byte[] PublicKeyAlgorithm { get; private set; } + public byte[] PublicKeyAlgorithm { get; } /// - /// Gets or sets the public host key and certificates for client host. + /// Gets the public host key and certificates for client host. /// /// /// The public host key. /// - public byte[] PublicHostKey { get; private set; } + public byte[] PublicHostKey { get; } /// - /// Gets or sets the name of the client host as ASCII encoded byte array. + /// Gets the name of the client host as ASCII encoded byte array. /// /// /// The name of the client host. /// - public byte[] ClientHostName { get; private set; } + public byte[] ClientHostName { get; } /// - /// Gets or sets the client username on the client host as UTF-8 encoded byte array. + /// Gets the client username on the client host as UTF-8 encoded byte array. /// /// /// The client username. /// - public byte[] ClientUsername { get; private set; } + public byte[] ClientUsername { get; } /// - /// Gets or sets the signature. + /// Gets the signature. /// /// /// The signature. /// - public byte[] Signature { get; private set; } + public byte[] Signature { get; } /// /// Gets the size of the message in bytes. diff --git a/src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs b/src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs index 76c98f364..7e88d2828 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelDataMessage.cs @@ -11,7 +11,7 @@ public class ChannelDataMessage : ChannelMessage internal const byte MessageNumber = 94; /// - /// Gets or sets message data. + /// Gets the message data. /// /// /// The data. @@ -27,7 +27,7 @@ public class ChannelDataMessage : ChannelMessage /// /// The zero-based offset in at which the data begins. /// - public int Offset { get; set; } + public int Offset { get; private set; } /// /// Gets the number of bytes of to read or write. @@ -35,7 +35,7 @@ public class ChannelDataMessage : ChannelMessage /// /// The number of bytes of to read or write. /// - public int Size { get; set; } + public int Size { get; private set; } /// /// Gets the size of the message in bytes. @@ -75,7 +75,9 @@ public ChannelDataMessage(uint localChannelNumber, byte[] data) : base(localChannelNumber) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } Data = data; Offset = 0; @@ -93,7 +95,9 @@ public ChannelDataMessage(uint localChannelNumber, byte[] data, int offset, int : base(localChannelNumber) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } Data = data; Offset = offset; @@ -106,6 +110,7 @@ public ChannelDataMessage(uint localChannelNumber, byte[] data, int offset, int protected override void LoadData() { base.LoadData(); + Data = ReadBinary(); Offset = 0; Size = Data.Length; @@ -117,6 +122,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinary(Data, Offset, Size); } } diff --git a/src/Renci.SshNet/Messages/Connection/ChannelMessage.cs b/src/Renci.SshNet/Messages/Connection/ChannelMessage.cs index b47852b95..e1d6ee995 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelMessage.cs @@ -32,14 +32,14 @@ protected override int BufferCapacity } /// - /// Initializes a new . + /// Initializes a new instance of the class. /// protected ChannelMessage() { } /// - /// Initializes a new with the specified local channel number. + /// Initializes a new instance of the class with the specified local channel number. /// /// The local channel number. protected ChannelMessage(uint localChannelNumber) @@ -64,10 +64,10 @@ protected override void SaveData() } /// - /// Returns a that represents this instance. + /// Returns a that represents this instance. /// /// - /// A that represents this instance. + /// A that represents this instance. /// public override string ToString() { diff --git a/src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs b/src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs index 1f8bb3e92..b4cac43b4 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs @@ -76,7 +76,7 @@ protected override int BufferCapacity /// public ChannelOpenMessage() { - // Required for dynamicly loading request type when it comes from the server + // Required for dynamicly loading request type when it comes from the server } /// @@ -90,7 +90,9 @@ public ChannelOpenMessage() public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maximumPacketSize, ChannelOpenInfo info) { if (info == null) - throw new ArgumentNullException("info"); + { + throw new ArgumentNullException(nameof(info)); + } ChannelType = Ascii.GetBytes(info.ChannelType); LocalChannelNumber = channelNumber; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs index 8ad47fbb7..596043915 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelOpen/DirectTcpipChannelInfo.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Messages.Connection /// /// Used to open "direct-tcpip" channel type /// - internal class DirectTcpipChannelInfo : ChannelOpenInfo + internal sealed class DirectTcpipChannelInfo : ChannelOpenInfo { private byte[] _hostToConnect; private byte[] _originatorAddress; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs index 64d0ebba9..aec13dc01 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelOpen/ForwardedTcpipChannelInfo.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Messages.Connection /// /// Used to open "forwarded-tcpip" channel type /// - internal class ForwardedTcpipChannelInfo : ChannelOpenInfo + internal sealed class ForwardedTcpipChannelInfo : ChannelOpenInfo { private byte[] _connectedAddress; private byte[] _originatorAddress; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs index bfe047688..edcc9dae9 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelOpen/SessionChannelOpenInfo.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Messages.Connection /// /// Used to open "session" channel type /// - internal class SessionChannelOpenInfo : ChannelOpenInfo + internal sealed class SessionChannelOpenInfo : ChannelOpenInfo { /// /// Specifies channel open type diff --git a/src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs index 6f62cfdaf..6eef2d510 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelOpen/X11ChannelOpenInfo.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Messages.Connection /// /// Used to open "x11" channel type /// - internal class X11ChannelOpenInfo : ChannelOpenInfo + internal sealed class X11ChannelOpenInfo : ChannelOpenInfo { private byte[] _originatorAddress; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs index 0cadd6379..472f8cb8e 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs @@ -3,7 +3,7 @@ /// /// Represents "break" type channel request information /// - internal class BreakRequestInfo : RequestInfo + internal sealed class BreakRequestInfo : RequestInfo { /// /// Channel request name diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs index 673f4c2bf..877dd4326 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs @@ -4,14 +4,14 @@ namespace Renci.SshNet.Messages.Connection { /// - /// Represents "exec" type channel request information + /// Represents "exec" type channel request information. /// internal class ExecRequestInfo : RequestInfo { private byte[] _command; /// - /// Channel request name + /// Channel request name. /// public const string Name = "exec"; @@ -80,9 +80,14 @@ public ExecRequestInfo(string command, Encoding encoding) : this() { if (command == null) - throw new ArgumentNullException("command"); + { + throw new ArgumentNullException(nameof(command)); + } + if (encoding == null) - throw new ArgumentNullException("encoding"); + { + throw new ArgumentNullException(nameof(encoding)); + } _command = encoding.GetBytes(command); Encoding = encoding; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs index 6fdc681cb..af57bb2d7 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs @@ -1,15 +1,16 @@ -using Renci.SshNet.Common; -using System.Collections.Generic; +using System.Collections.Generic; + +using Renci.SshNet.Common; namespace Renci.SshNet.Messages.Connection { /// - /// Represents "pty-req" type channel request information + /// Represents "pty-req" type channel request information. /// internal class PseudoTerminalRequestInfo : RequestInfo { /// - /// Channel request name + /// Channel request name. /// public const string Name = "pty-req"; @@ -98,7 +99,7 @@ public PseudoTerminalRequestInfo() /// The TERM environment variable which a identifier for the text window’s capabilities. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. /// The terminal mode values. /// @@ -153,7 +154,7 @@ protected override void SaveData() else { // when there are no terminal mode, the length of the string is zero - Write((uint) 0); + Write(0u); } } } diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs index 4b570d708..42fc9cf1d 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/ShellRequestInfo.cs @@ -3,7 +3,7 @@ /// /// Represents "shell" type channel request information /// - internal class ShellRequestInfo : RequestInfo + internal sealed class ShellRequestInfo : RequestInfo { /// /// Channel request name diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs index 493681b44..bb69e5ed2 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs @@ -3,7 +3,7 @@ /// /// Represents "signal" type channel request information /// - internal class SignalRequestInfo : RequestInfo + internal sealed class SignalRequestInfo : RequestInfo { private byte[] _signalName; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs index 1af72be8e..6871b9fe3 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs @@ -3,7 +3,7 @@ /// /// Represents "subsystem" type channel request information /// - internal class SubsystemRequestInfo : RequestInfo + internal sealed class SubsystemRequestInfo : RequestInfo { private byte[] _subsystemName; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs index 4f0813bd8..edcd9af54 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/WindowChangeRequestInfo.cs @@ -3,7 +3,7 @@ /// /// Represents "window-change" type channel request information /// - internal class WindowChangeRequestInfo : RequestInfo + internal sealed class WindowChangeRequestInfo : RequestInfo { /// /// Channe request name diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs index 89ebfe4f9..4d27872eb 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs @@ -1,14 +1,14 @@ namespace Renci.SshNet.Messages.Connection { /// - /// Represents "x11-req" type channel request information + /// Represents "x11-req" type channel request information. /// - internal class X11ForwardingRequestInfo : RequestInfo + internal sealed class X11ForwardingRequestInfo : RequestInfo { private byte[] _authenticationProtocol; /// - /// Channel request name + /// Channel request name. /// public const string Name = "x11-req"; @@ -27,7 +27,7 @@ public override string RequestName /// Gets or sets a value indicating whether it is a single connection. /// /// - /// true if it is a single connection; otherwise, false. + /// true if it is a single connection; otherwise, false. /// public bool IsSingleConnection { get; set; } diff --git a/src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs b/src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs index ff10a73ab..b53578de9 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelRequest/XonXoffRequestInfo.cs @@ -3,10 +3,10 @@ /// /// Represents "xon-xoff" type channel request information /// - internal class XonXoffRequestInfo : RequestInfo + internal sealed class XonXoffRequestInfo : RequestInfo { /// - /// Channel request type + /// Channel request type. /// public const string Name = "xon-xoff"; diff --git a/src/Renci.SshNet/Messages/Connection/ChannelWindowAdjustMessage.cs b/src/Renci.SshNet/Messages/Connection/ChannelWindowAdjustMessage.cs index 364b81300..315c98c8a 100644 --- a/src/Renci.SshNet/Messages/Connection/ChannelWindowAdjustMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/ChannelWindowAdjustMessage.cs @@ -32,7 +32,6 @@ protected override int BufferCapacity /// public ChannelWindowAdjustMessage() { - } /// @@ -52,6 +51,7 @@ public ChannelWindowAdjustMessage(uint localChannelNumber, uint bytesToAdd) protected override void LoadData() { base.LoadData(); + BytesToAdd = ReadUInt32(); } @@ -61,6 +61,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + Write(BytesToAdd); } diff --git a/src/Renci.SshNet/Messages/Connection/RequestFailureMessage.cs b/src/Renci.SshNet/Messages/Connection/RequestFailureMessage.cs index af9df7501..553f95473 100644 --- a/src/Renci.SshNet/Messages/Connection/RequestFailureMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/RequestFailureMessage.cs @@ -1,5 +1,4 @@ - -namespace Renci.SshNet.Messages.Connection +namespace Renci.SshNet.Messages.Connection { /// /// Represents SSH_MSG_REQUEST_FAILURE message. diff --git a/src/Renci.SshNet/Messages/Connection/RequestSuccessMessage.cs b/src/Renci.SshNet/Messages/Connection/RequestSuccessMessage.cs index b456efe85..00ad1059d 100644 --- a/src/Renci.SshNet/Messages/Connection/RequestSuccessMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/RequestSuccessMessage.cs @@ -22,8 +22,12 @@ protected override int BufferCapacity get { var capacity = base.BufferCapacity; + if (BoundPort.HasValue) + { capacity += 4; // BoundPort + } + return capacity; } } @@ -33,7 +37,6 @@ protected override int BufferCapacity /// public RequestSuccessMessage() { - } /// @@ -51,7 +54,9 @@ public RequestSuccessMessage(uint boundPort) protected override void LoadData() { if (!IsEndOfData) + { BoundPort = ReadUInt32(); + } } /// @@ -60,7 +65,9 @@ protected override void LoadData() protected override void SaveData() { if (BoundPort.HasValue) + { Write(BoundPort.Value); + } } internal override void Process(Session session) diff --git a/src/Renci.SshNet/Messages/Connection/TcpIpForwardGlobalRequestMessage.cs b/src/Renci.SshNet/Messages/Connection/TcpIpForwardGlobalRequestMessage.cs index 83d0b013c..fdfbfb8df 100644 --- a/src/Renci.SshNet/Messages/Connection/TcpIpForwardGlobalRequestMessage.cs +++ b/src/Renci.SshNet/Messages/Connection/TcpIpForwardGlobalRequestMessage.cs @@ -2,7 +2,7 @@ namespace Renci.SshNet.Messages.Connection { - internal class TcpIpForwardGlobalRequestMessage : GlobalRequestMessage + internal sealed class TcpIpForwardGlobalRequestMessage : GlobalRequestMessage { private byte[] _addressToBind; diff --git a/src/Renci.SshNet/Messages/Message.cs b/src/Renci.SshNet/Messages/Message.cs index 2bbfb7b9e..d2fc3274a 100644 --- a/src/Renci.SshNet/Messages/Message.cs +++ b/src/Renci.SshNet/Messages/Message.cs @@ -1,7 +1,8 @@ -using System.IO; -using Renci.SshNet.Common; -using System.Globalization; +using System.Globalization; +using System.IO; + using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; using Renci.SshNet.Compression; namespace Renci.SshNet.Messages @@ -30,7 +31,7 @@ protected override int BufferCapacity /// protected override void WriteBytes(SshDataStream stream) { - var enumerator = GetType().GetCustomAttributes(true).GetEnumerator(); + var enumerator = GetType().GetCustomAttributes(inherit: true).GetEnumerator(); try { if (!enumerator.MoveNext()) @@ -64,7 +65,7 @@ internal byte[] GetPacket(byte paddingMultiplier, Compressor compressor) // * 4 bytes for the outbound packet sequence // * 4 bytes for the packet data length // * one byte for the packet padding length - sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin); + _ = sshDataStream.Seek(outboundPacketSequenceSize + 4 + 1, SeekOrigin.Begin); if (compressor != null) { @@ -99,12 +100,12 @@ internal byte[] GetPacket(byte paddingMultiplier, Compressor compressor) var packetDataLength = GetPacketDataLength(messageLength, paddingLength); // skip bytes for outbound packet sequence - sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); + _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); // add packet data length sshDataStream.Write(packetDataLength); - // add packet padding length + // add packet padding length sshDataStream.WriteByte(paddingLength); } else @@ -120,12 +121,12 @@ internal byte[] GetPacket(byte paddingMultiplier, Compressor compressor) sshDataStream = new SshDataStream(packetLength + paddingLength + outboundPacketSequenceSize); // skip bytes for outbound packet sequenceSize - sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); + _ = sshDataStream.Seek(outboundPacketSequenceSize, SeekOrigin.Begin); // add packet data length sshDataStream.Write(packetDataLength); - // add packet padding length + // add packet padding length sshDataStream.WriteByte(paddingLength); // add message payload @@ -148,10 +149,12 @@ private static uint GetPacketDataLength(int messageLength, byte paddingLength) private static byte GetPaddingLength(byte paddingMultiplier, long packetLength) { var paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1)); + if (paddingLength < paddingMultiplier) { paddingLength += paddingMultiplier; } + return paddingLength; } @@ -163,8 +166,7 @@ private static byte GetPaddingLength(byte paddingMultiplier, long packetLength) /// public override string ToString() { - var enumerator = GetType().GetCustomAttributes(true).GetEnumerator(); - try + using (var enumerator = GetType().GetCustomAttributes(inherit: true).GetEnumerator()) { if (!enumerator.MoveNext()) { @@ -173,10 +175,6 @@ public override string ToString() return enumerator.Current.Name; } - finally - { - enumerator.Dispose(); - } } /// @@ -185,4 +183,4 @@ public override string ToString() /// The for which to process the current message. internal abstract void Process(Session session); } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Messages/Transport/IgnoreMessage.cs b/src/Renci.SshNet/Messages/Transport/IgnoreMessage.cs index 580cd3b21..72fc10699 100644 --- a/src/Renci.SshNet/Messages/Transport/IgnoreMessage.cs +++ b/src/Renci.SshNet/Messages/Transport/IgnoreMessage.cs @@ -50,7 +50,9 @@ protected override int BufferCapacity public IgnoreMessage(byte[] data) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } Data = data; } diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs index c8af4724d..381c534b9 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs @@ -4,7 +4,7 @@ /// Represents SSH_MSG_KEX_DH_GEX_INIT message. /// [Message("SSH_MSG_KEX_DH_GEX_INIT", 32)] - internal class KeyExchangeDhGroupExchangeInit : Message, IKeyExchangedAllowed + internal sealed class KeyExchangeDhGroupExchangeInit : Message, IKeyExchangedAllowed { /// /// Gets the E value. diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeReply.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeReply.cs index 88bad74e2..7b446d962 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeReply.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeReply.cs @@ -1,19 +1,19 @@ -using Renci.SshNet.Common; - -namespace Renci.SshNet.Messages.Transport +namespace Renci.SshNet.Messages.Transport { /// /// Represents SSH_MSG_KEX_DH_GEX_REPLY message. /// [Message("SSH_MSG_KEX_DH_GEX_REPLY", MessageNumber)] - internal class KeyExchangeDhGroupExchangeReply : Message + internal sealed class KeyExchangeDhGroupExchangeReply : Message { internal const byte MessageNumber = 33; /// - /// Gets server public host key and certificates + /// Gets server public host key and certificates. /// - /// The host key. + /// + /// The host key. + /// public byte[] HostKey { get; private set; } /// diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs index d31335910..9bb6c6bc8 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs @@ -4,12 +4,12 @@ /// Represents SSH_MSG_KEX_DH_GEX_REQUEST message. /// [Message("SSH_MSG_KEX_DH_GEX_REQUEST", MessageNumber)] - internal class KeyExchangeDhGroupExchangeRequest : Message, IKeyExchangedAllowed + internal sealed class KeyExchangeDhGroupExchangeRequest : Message, IKeyExchangedAllowed { internal const byte MessageNumber = 34; /// - /// Gets or sets the minimal size in bits of an acceptable group. + /// Gets the minimum size, in bits, of an acceptable group. /// /// /// The minimum. @@ -17,7 +17,7 @@ internal class KeyExchangeDhGroupExchangeRequest : Message, IKeyExchangedAllowed public uint Minimum { get; private set; } /// - /// Gets or sets the preferred size in bits of the group the server will send. + /// Gets the preferred size, in bits, of the group the server will send. /// /// /// The preferred. @@ -25,7 +25,7 @@ internal class KeyExchangeDhGroupExchangeRequest : Message, IKeyExchangedAllowed public uint Preferred { get; private set; } /// - /// Gets or sets the maximal size in bits of an acceptable group. + /// Gets the maximum size, in bits, of an acceptable group. /// /// /// The maximum. diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs index 9d1d76850..5b681d1b4 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs @@ -4,7 +4,7 @@ /// Represents SSH_MSG_KEXDH_INIT message. /// [Message("SSH_MSG_KEXDH_INIT", 30)] - internal class KeyExchangeDhInitMessage : Message, IKeyExchangedAllowed + internal sealed class KeyExchangeDhInitMessage : Message, IKeyExchangedAllowed { /// /// Gets the E value. diff --git a/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs b/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs index ddcf03f19..4bd508f54 100644 --- a/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs +++ b/src/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs @@ -7,7 +7,7 @@ namespace Renci.SshNet.Messages.Transport /// Represents SSH_MSG_KEXECDH_INIT message. /// [Message("SSH_MSG_KEX_ECDH_INIT", 30)] - internal class KeyExchangeEcdhInitMessage : Message, IKeyExchangedAllowed + internal sealed class KeyExchangeEcdhInitMessage : Message, IKeyExchangedAllowed { /// /// Gets the client's ephemeral contribution to the ECDH exchange, encoded as an octet string @@ -75,4 +75,4 @@ internal override void Process(Session session) throw new NotImplementedException(); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/NetConfClient.cs b/src/Renci.SshNet/NetConfClient.cs index b7ec82ec2..bbedca3c2 100644 --- a/src/Renci.SshNet/NetConfClient.cs +++ b/src/Renci.SshNet/NetConfClient.cs @@ -1,13 +1,13 @@ using System; -using Renci.SshNet.Common; -using Renci.SshNet.NetConf; -using System.Xml; using System.Diagnostics.CodeAnalysis; using System.Net; +using System.Xml; + +using Renci.SshNet.Common; +using Renci.SshNet.NetConf; namespace Renci.SshNet { - // TODO: Please help with documentation here, as I don't know the details, specially for the methods not documented. /// /// Contains operation for working with NetConf server. /// @@ -16,7 +16,7 @@ public class NetConfClient : BaseClient private int _operationTimeout; /// - /// Holds instance that used to communicate to the server + /// Holds instance that used to communicate to the server. /// private INetConfSession _netConfSession; @@ -27,14 +27,20 @@ public class NetConfClient : BaseClient /// The timeout to wait until an operation completes. The default value is negative /// one (-1) milliseconds, which indicates an infinite time-out period. /// - /// represents a value that is less than -1 or greater than milliseconds. - public TimeSpan OperationTimeout { - get { return TimeSpan.FromMilliseconds(_operationTimeout); } + /// represents a value that is less than -1 or greater than milliseconds. + public TimeSpan OperationTimeout + { + get + { + return TimeSpan.FromMilliseconds(_operationTimeout); + } set { var timeoutInMilliseconds = value.TotalMilliseconds; - if (timeoutInMilliseconds < -1d || timeoutInMilliseconds > int.MaxValue) - throw new ArgumentOutOfRangeException("value", "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + if (timeoutInMilliseconds is < -1d or > int.MaxValue) + { + throw new ArgumentOutOfRangeException(nameof(value), "The timeout must represent a value between -1 and Int32.MaxValue, inclusive."); + } _operationTimeout = (int) timeoutInMilliseconds; } @@ -51,15 +57,13 @@ internal INetConfSession NetConfSession get { return _netConfSession; } } - #region Constructors - /// /// Initializes a new instance of the class. /// /// The connection info. /// is null. public NetConfClient(ConnectionInfo connectionInfo) - : this(connectionInfo, false) + : this(connectionInfo, ownsConnectionInfo: false) { } @@ -75,7 +79,7 @@ public NetConfClient(ConnectionInfo connectionInfo) /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public NetConfClient(string host, int port, string username, string password) - : this(new PasswordConnectionInfo(host, port, username, password), true) + : this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true) { } @@ -104,7 +108,7 @@ public NetConfClient(string host, string username, string password) /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public NetConfClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) - : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) + : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true) { } @@ -155,8 +159,6 @@ internal NetConfClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, I AutomaticMessageIdHandling = true; } - #endregion - /// /// Gets the NetConf server capabilities. /// @@ -193,7 +195,9 @@ public XmlDocument ClientCapabilities /// Sends the receive RPC. /// /// The RPC. - /// Reply message to RPC request + /// + /// Reply message to RPC request. + /// /// Client is not connected. public XmlDocument SendReceiveRpc(XmlDocument rpc) { @@ -204,7 +208,9 @@ public XmlDocument SendReceiveRpc(XmlDocument rpc) /// Sends the receive RPC. /// /// The XML. - /// Reply message to RPC request + /// + /// Reply message to RPC request. + /// public XmlDocument SendReceiveRpc(string xml) { var rpc = new XmlDocument(); @@ -215,7 +221,9 @@ public XmlDocument SendReceiveRpc(string xml) /// /// Sends the close RPC. /// - /// Reply message to closing RPC request + /// + /// Reply message to closing RPC request. + /// /// Client is not connected. public XmlDocument SendCloseRpc() { @@ -245,7 +253,7 @@ protected override void OnDisconnecting() } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) @@ -277,4 +285,4 @@ private INetConfSession CreateAndConnectNetConfSession() } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Netconf/NetConfSession.cs b/src/Renci.SshNet/Netconf/NetConfSession.cs index 14ba00a6e..6e4e251f7 100644 --- a/src/Renci.SshNet/Netconf/NetConfSession.cs +++ b/src/Renci.SshNet/Netconf/NetConfSession.cs @@ -1,10 +1,11 @@ using System; using System.Globalization; using System.Text; +using System.Text.RegularExpressions; using System.Threading; -using Renci.SshNet.Common; using System.Xml; -using System.Text.RegularExpressions; + +using Renci.SshNet.Common; namespace Renci.SshNet.NetConf { @@ -14,8 +15,8 @@ internal class NetConfSession : SubsystemSession, INetConfSession private readonly StringBuilder _data = new StringBuilder(); private bool _usingFramingProtocol; - private EventWaitHandle _serverCapabilitiesConfirmed = new AutoResetEvent(false); - private EventWaitHandle _rpcReplyReceived = new AutoResetEvent(false); + private EventWaitHandle _serverCapabilitiesConfirmed = new AutoResetEvent(initialState: false); + private EventWaitHandle _rpcReplyReceived = new AutoResetEvent(initialState: false); private StringBuilder _rpcReply = new StringBuilder(); private int _messageId; @@ -46,12 +47,11 @@ public NetConfSession(ISession session, int operationTimeout) "" + "" + ""); - } public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandling) { - _data.Clear(); + _ = _data.Clear(); XmlNamespaceManager nsMgr = null; if (automaticMessageIdHandling) @@ -61,15 +61,16 @@ public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandli nsMgr.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0"); rpc.SelectSingleNode("/nc:rpc/@message-id", nsMgr).Value = _messageId.ToString(CultureInfo.InvariantCulture); } + _rpcReply = new StringBuilder(); - _rpcReplyReceived.Reset(); + _ = _rpcReplyReceived.Reset(); var reply = new XmlDocument(); if (_usingFramingProtocol) { var command = new StringBuilder(rpc.InnerXml.Length + 10); - command.AppendFormat("\n#{0}\n", rpc.InnerXml.Length); - command.Append(rpc.InnerXml); - command.Append("\n##\n"); + _ = command.AppendFormat(CultureInfo.InvariantCulture, "\n#{0}\n", rpc.InnerXml.Length); + _ = command.Append(rpc.InnerXml); + _ = command.Append("\n##\n"); SendData(Encoding.UTF8.GetBytes(command.ToString())); WaitOnHandle(_rpcReplyReceived, OperationTimeout); @@ -81,6 +82,7 @@ public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandli WaitOnHandle(_rpcReplyReceived, OperationTimeout); reply.LoadXml(_rpcReply.ToString()); } + if (automaticMessageIdHandling) { var replyId = rpc.SelectSingleNode("/nc:rpc/@message-id", nsMgr).Value; @@ -89,14 +91,15 @@ public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandli throw new NetConfServerException("The rpc message id does not match the rpc-reply message id."); } } + return reply; } protected override void OnChannelOpen() { - _data.Clear(); + _ = _data.Clear(); - var message = string.Format("{0}{1}", ClientCapabilities.InnerXml, Prompt); + var message = string.Concat(ClientCapabilities.InnerXml, Prompt); SendData(Encoding.UTF8.GetBytes(message)); @@ -107,21 +110,22 @@ protected override void OnDataReceived(byte[] data) { var chunk = Encoding.UTF8.GetString(data); - if (ServerCapabilities == null) // This must be server capabilities, old protocol + if (ServerCapabilities == null) { - _data.Append(chunk); + _ = _data.Append(chunk); if (!chunk.Contains(Prompt)) { return; } + try { - chunk = _data.ToString(); - _data.Clear(); + chunk = _data.ToString(); + _ = _data.Clear(); ServerCapabilities = new XmlDocument(); - ServerCapabilities.LoadXml(chunk.Replace(Prompt, "")); + ServerCapabilities.LoadXml(chunk.Replace(Prompt, string.Empty)); } catch (XmlException e) { @@ -131,9 +135,9 @@ protected override void OnDataReceived(byte[] data) var nsMgr = new XmlNamespaceManager(ServerCapabilities.NameTable); nsMgr.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0"); - _usingFramingProtocol = (ServerCapabilities.SelectSingleNode("/nc:hello/nc:capabilities/nc:capability[text()='urn:ietf:params:netconf:base:1.1']", nsMgr) != null); + _usingFramingProtocol = ServerCapabilities.SelectSingleNode("/nc:hello/nc:capabilities/nc:capability[text()='urn:ietf:params:netconf:base:1.1']", nsMgr) != null; - _serverCapabilitiesConfirmed.Set(); + _ = _serverCapabilitiesConfirmed.Set(); } else if (_usingFramingProtocol) { @@ -146,30 +150,31 @@ protected override void OnDataReceived(byte[] data) { break; } - var fractionLength = Convert.ToInt32(match.Groups["length"].Value); - _rpcReply.Append(chunk, position + match.Index + match.Length, fractionLength); + + var fractionLength = Convert.ToInt32(match.Groups["length"].Value, CultureInfo.InvariantCulture); + _ = _rpcReply.Append(chunk, position + match.Index + match.Length, fractionLength); position += match.Index + match.Length + fractionLength; } + if (Regex.IsMatch(chunk.Substring(position), @"\n##\n")) { - _rpcReplyReceived.Set(); + _ = _rpcReplyReceived.Set(); } } - else // Old protocol + else { - _data.Append(chunk); + _ = _data.Append(chunk); if (!chunk.Contains(Prompt)) { return; - //throw new NetConfServerException("Server XML message does not end with the prompt " + _prompt); } - + chunk = _data.ToString(); - _data.Clear(); + _ = _data.Clear(); - _rpcReply.Append(chunk.Replace(Prompt, "")); - _rpcReplyReceived.Set(); + _ = _rpcReply.Append(chunk.Replace(Prompt, string.Empty)); + _ = _rpcReplyReceived.Set(); } } diff --git a/src/Renci.SshNet/NoneAuthenticationMethod.cs b/src/Renci.SshNet/NoneAuthenticationMethod.cs index 93586ade9..468d46559 100644 --- a/src/Renci.SshNet/NoneAuthenticationMethod.cs +++ b/src/Renci.SshNet/NoneAuthenticationMethod.cs @@ -1,20 +1,22 @@ using System; using System.Threading; -using Renci.SshNet.Messages.Authentication; + using Renci.SshNet.Messages; +using Renci.SshNet.Messages.Authentication; namespace Renci.SshNet { /// - /// Provides functionality for "none" authentication method + /// Provides functionality for "none" authentication method. /// public class NoneAuthenticationMethod : AuthenticationMethod, IDisposable { private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false); + private bool _isDisposed; /// - /// Gets connection name + /// Gets the name of the authentication method. /// public override string Name { @@ -42,7 +44,9 @@ public NoneAuthenticationMethod(string username) public override AuthenticationResult Authenticate(Session session) { if (session == null) - throw new ArgumentNullException("session"); + { + throw new ArgumentNullException(nameof(session)); + } session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived; @@ -65,43 +69,45 @@ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEve { _authenticationResult = AuthenticationResult.Success; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e) { if (e.Message.PartialSuccess) + { _authenticationResult = AuthenticationResult.PartialSuccess; + } else + { _authenticationResult = AuthenticationResult.Failure; + } // Copy allowed authentication methods AllowedAuthentications = e.Message.AllowedAuthentications; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } - - #region IDisposable Members - - private bool _isDisposed; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -117,15 +123,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~NoneAuthenticationMethod() { - Dispose(false); + Dispose(disposing: false); } - - #endregion - } } diff --git a/src/Renci.SshNet/PasswordAuthenticationMethod.cs b/src/Renci.SshNet/PasswordAuthenticationMethod.cs index 48e46bef3..a60b40ebf 100644 --- a/src/Renci.SshNet/PasswordAuthenticationMethod.cs +++ b/src/Renci.SshNet/PasswordAuthenticationMethod.cs @@ -1,10 +1,11 @@ using System; using System.Text; using System.Threading; + using Renci.SshNet.Abstractions; using Renci.SshNet.Common; -using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Messages; +using Renci.SshNet.Messages.Authentication; namespace Renci.SshNet { @@ -13,15 +14,16 @@ namespace Renci.SshNet /// public class PasswordAuthenticationMethod : AuthenticationMethod, IDisposable { + private readonly RequestMessage _requestMessage; + private readonly byte[] _password; private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; private Session _session; private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false); private Exception _exception; - private readonly RequestMessage _requestMessage; - private readonly byte[] _password; + private bool _isDisposed; /// - /// Gets authentication method name + /// Gets the name of the authentication method. /// public override string Name { @@ -67,7 +69,9 @@ public PasswordAuthenticationMethod(string username, byte[] password) : base(username) { if (password == null) - throw new ArgumentNullException("password"); + { + throw new ArgumentNullException(nameof(password)); + } _password = password; _requestMessage = new RequestMessagePassword(ServiceName.Connection, Username, _password); @@ -84,7 +88,9 @@ public PasswordAuthenticationMethod(string username, byte[] password) public override AuthenticationResult Authenticate(Session session) { if (session == null) - throw new ArgumentNullException("session"); + { + throw new ArgumentNullException(nameof(session)); + } _session = session; @@ -107,7 +113,9 @@ public override AuthenticationResult Authenticate(Session session) } if (_exception != null) + { throw _exception; + } return _authenticationResult; } @@ -116,20 +124,24 @@ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEve { _authenticationResult = AuthenticationResult.Success; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e) { if (e.Message.PartialSuccess) + { _authenticationResult = AuthenticationResult.PartialSuccess; + } else + { _authenticationResult = AuthenticationResult.Failure; + } - // Copy allowed authentication methods + // Copy allowed authentication methods AllowedAuthentications = e.Message.AllowedAuthentications; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationPasswordChangeRequiredReceived(object sender, MessageEventArgs e) @@ -142,45 +154,40 @@ private void Session_UserAuthenticationPasswordChangeRequiredReceived(object sen { var eventArgs = new AuthenticationPasswordChangeEventArgs(Username); - // Raise an event to allow user to supply a new password - if (PasswordExpired != null) - { - PasswordExpired(this, eventArgs); - } + // Raise an event to allow user to supply a new password + PasswordExpired?.Invoke(this, eventArgs); - // Send new authentication request with new password + // Send new authentication request with new password _session.SendMessage(new RequestMessagePassword(ServiceName.Connection, Username, _password, eventArgs.NewPassword)); } catch (Exception exp) { _exception = exp; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } }); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; - + } + if (disposing) { var authenticationCompleted = _authenticationCompleted; @@ -195,14 +202,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~PasswordAuthenticationMethod() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/PasswordConnectionInfo.cs b/src/Renci.SshNet/PasswordConnectionInfo.cs index d42ff5094..28317411d 100644 --- a/src/Renci.SshNet/PasswordConnectionInfo.cs +++ b/src/Renci.SshNet/PasswordConnectionInfo.cs @@ -15,6 +15,8 @@ namespace Renci.SshNet /// public class PasswordConnectionInfo : ConnectionInfo, IDisposable { + private bool _isDisposed; + /// /// Occurs when user's password has expired and needs to be changed. /// @@ -249,8 +251,7 @@ public PasswordConnectionInfo(string host, int port, string username, byte[] pas { foreach (var authenticationMethod in AuthenticationMethods) { - var pwdAuthentication = authenticationMethod as PasswordAuthenticationMethod; - if (pwdAuthentication != null) + if (authenticationMethod is PasswordAuthenticationMethod pwdAuthentication) { pwdAuthentication.PasswordExpired += AuthenticationMethod_PasswordExpired; } @@ -259,33 +260,28 @@ public PasswordConnectionInfo(string host, int port, string username, byte[] pas private void AuthenticationMethod_PasswordExpired(object sender, AuthenticationPasswordChangeEventArgs e) { - if (PasswordExpired != null) - { - PasswordExpired(sender, e); - } + PasswordExpired?.Invoke(sender, e); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -293,8 +289,7 @@ protected virtual void Dispose(bool disposing) { foreach (var authenticationMethod in AuthenticationMethods) { - var disposable = authenticationMethod as IDisposable; - if (disposable != null) + if (authenticationMethod is IDisposable disposable) { disposable.Dispose(); } @@ -306,17 +301,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~PasswordConnectionInfo() { - // Do not re-create Dispose clean-up code here. - // Calling Dispose(false) is optimal in terms of - // readability and maintainability. - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs index 43d80b506..25f3f7605 100644 --- a/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs +++ b/src/Renci.SshNet/PrivateKeyAuthenticationMethod.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using Renci.SshNet.Messages.Authentication; -using Renci.SshNet.Messages; -using Renci.SshNet.Common; using System.Threading; +using Renci.SshNet.Common; +using Renci.SshNet.Messages; +using Renci.SshNet.Messages.Authentication; + namespace Renci.SshNet { /// @@ -16,9 +17,10 @@ public class PrivateKeyAuthenticationMethod : AuthenticationMethod, IDisposable private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; private EventWaitHandle _authenticationCompleted = new ManualResetEvent(false); private bool _isSignatureRequired; + private bool _isDisposed; /// - /// Gets authentication method name + /// Gets the name of the authentication method. /// public override string Name { @@ -40,7 +42,9 @@ public PrivateKeyAuthenticationMethod(string username, params IPrivateKeySource[ : base(username) { if (keyFiles == null) - throw new ArgumentNullException("keyFiles"); + { + throw new ArgumentNullException(nameof(keyFiles)); + } KeyFiles = new Collection(keyFiles); } @@ -64,7 +68,7 @@ public override AuthenticationResult Authenticate(Session session) { foreach (var keyFile in KeyFiles) { - _authenticationCompleted.Reset(); + _ = _authenticationCompleted.Reset(); _isSignatureRequired = false; var message = new RequestMessagePublicKey(ServiceName.Connection, @@ -74,20 +78,20 @@ public override AuthenticationResult Authenticate(Session session) if (KeyFiles.Count < 2) { - // If only one key file provided then send signature for very first request + // If only one key file provided then send signature for very first request var signatureData = new SignatureData(message, session.SessionId).GetBytes(); message.Signature = keyFile.HostKey.Sign(signatureData); } - // Send public key authentication request + // Send public key authentication request session.SendMessage(message); session.WaitOnHandle(_authenticationCompleted); if (_isSignatureRequired) { - _authenticationCompleted.Reset(); + _ = _authenticationCompleted.Reset(); var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, Username, @@ -98,7 +102,7 @@ public override AuthenticationResult Authenticate(Session session) signatureMessage.Signature = keyFile.HostKey.Sign(signatureData); - // Send public key authentication request with signature + // Send public key authentication request with signature session.SendMessage(signatureMessage); } @@ -125,38 +129,38 @@ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEve { _authenticationResult = AuthenticationResult.Success; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e) { if (e.Message.PartialSuccess) + { _authenticationResult = AuthenticationResult.PartialSuccess; + } else + { _authenticationResult = AuthenticationResult.Failure; + } - // Copy allowed authentication methods + // Copy allowed authentication methods AllowedAuthentications = e.Message.AllowedAuthentications; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } private void Session_UserAuthenticationPublicKeyReceived(object sender, MessageEventArgs e) { _isSignatureRequired = true; - _authenticationCompleted.Set(); + _ = _authenticationCompleted.Set(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -167,7 +171,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -183,17 +189,14 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~PrivateKeyAuthenticationMethod() { - Dispose(false); + Dispose(disposing: false); } - #endregion - - private class SignatureData : SshData + private sealed class SignatureData : SshData { private readonly RequestMessagePublicKey _message; @@ -250,4 +253,4 @@ protected override void SaveData() } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/PrivateKeyConnectionInfo.cs b/src/Renci.SshNet/PrivateKeyConnectionInfo.cs index 1f717631b..29b48ffaa 100644 --- a/src/Renci.SshNet/PrivateKeyConnectionInfo.cs +++ b/src/Renci.SshNet/PrivateKeyConnectionInfo.cs @@ -5,13 +5,15 @@ namespace Renci.SshNet { /// - /// Provides connection information when private key authentication method is used + /// Provides connection information when private key authentication method is used. /// /// /// /// public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable { + private bool _isDisposed; + /// /// Gets the key files used for authentication. /// @@ -30,7 +32,6 @@ public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyFile[] keyFiles) : this(host, DefaultPort, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles) { - } /// @@ -46,7 +47,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, params I } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// The port. @@ -61,7 +62,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// The port. @@ -77,7 +78,7 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. @@ -91,7 +92,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. @@ -106,7 +107,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// Connection username. @@ -122,7 +123,7 @@ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyTy } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Connection host. /// The port. @@ -139,27 +140,25 @@ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTyp KeyFiles = new Collection(keyFiles); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -168,8 +167,7 @@ protected virtual void Dispose(bool disposing) { foreach (var authenticationMethod in AuthenticationMethods) { - var disposable = authenticationMethod as IDisposable; - if (disposable != null) + if (authenticationMethod is IDisposable disposable) { disposable.Dispose(); } @@ -181,17 +179,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~PrivateKeyConnectionInfo() { - // Do not re-create Dispose clean-up code here. - // Calling Dispose(false) is optimal in terms of - // readability and maintainability. - Dispose(false); + Dispose(disposing: false); } - - #endregion } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/PrivateKeyFile.cs b/src/Renci.SshNet/PrivateKeyFile.cs index 5ec7f248d..4da514384 100644 --- a/src/Renci.SshNet/PrivateKeyFile.cs +++ b/src/Renci.SshNet/PrivateKeyFile.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using System.Text.RegularExpressions; + using Renci.SshNet.Abstractions; -using Renci.SshNet.Security; using Renci.SshNet.Common; -using System.Globalization; +using Renci.SshNet.Security; +using Renci.SshNet.Security.Cryptography; using Renci.SshNet.Security.Cryptography.Ciphers; using Renci.SshNet.Security.Cryptography.Ciphers.Modes; using Renci.SshNet.Security.Cryptography.Ciphers.Paddings; -using System.Diagnostics.CodeAnalysis; -using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet { @@ -68,8 +68,8 @@ public class PrivateKeyFile : IPrivateKeySource, IDisposable private static readonly Regex PrivateKeyRegex = new Regex(@"^-+ *BEGIN (?\w+( \w+)*) PRIVATE KEY *-+\r?\n((Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)|(Comment: ""?[^\r\n]*""?\r?\n))?(?([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k PRIVATE KEY *-+", RegexOptions.Compiled | RegexOptions.Multiline); - private Key _key; + private bool _isDisposed; /// /// Gets the host key. @@ -91,7 +91,7 @@ public PrivateKeyFile(Key key) /// The private key. public PrivateKeyFile(Stream privateKey) { - Open(privateKey, null); + Open(privateKey, passPhrase: null); } /// @@ -99,9 +99,11 @@ public PrivateKeyFile(Stream privateKey) /// /// Name of the file. /// is null or empty. - /// This method calls internally, this method does not catch exceptions from . + /// + /// This method calls internally, this method does not catch exceptions from . + /// public PrivateKeyFile(string fileName) - : this(fileName, null) + : this(fileName, passPhrase: null) { } @@ -111,11 +113,15 @@ public PrivateKeyFile(string fileName) /// Name of the file. /// The pass phrase. /// is null or empty, or is null. - /// This method calls internally, this method does not catch exceptions from . + /// + /// This method calls internally, this method does not catch exceptions from . + /// public PrivateKeyFile(string fileName, string passPhrase) { if (string.IsNullOrEmpty(fileName)) - throw new ArgumentNullException("fileName"); + { + throw new ArgumentNullException(nameof(fileName)); + } using (var keyFile = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { @@ -139,11 +145,12 @@ public PrivateKeyFile(Stream privateKey, string passPhrase) /// /// The private key. /// The pass phrase. - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "this._key disposed in Dispose(bool) method.")] private void Open(Stream privateKey, string passPhrase) { if (privateKey == null) - throw new ArgumentNullException("privateKey"); + { + throw new ArgumentNullException(nameof(privateKey)); + } Match privateKeyMatch; @@ -170,11 +177,15 @@ private void Open(Stream privateKey, string passPhrase) if (!string.IsNullOrEmpty(cipherName) && !string.IsNullOrEmpty(salt)) { if (string.IsNullOrEmpty(passPhrase)) + { throw new SshPassPhraseNullOrEmptyException("Private key is encrypted but passphrase is empty."); + } var binarySalt = new byte[salt.Length / 2]; for (var i = 0; i < binarySalt.Length; i++) + { binarySalt[i] = Convert.ToByte(salt.Substring(i * 2, 2), 16); + } CipherInfo cipher; switch (cipherName) @@ -234,7 +245,7 @@ private void Open(Stream privateKey, string passPhrase) throw new SshException("Invalid SSH2 private key."); } - reader.ReadUInt32(); // Read total bytes length including magic number + _ = reader.ReadUInt32(); // Read total bytes length including magic number var keyType = reader.ReadString(SshData.Ascii); var ssh2CipherName = reader.ReadString(SshData.Ascii); var blobSize = (int)reader.ReadUInt32(); @@ -258,23 +269,25 @@ private void Open(Stream privateKey, string passPhrase) throw new SshException(string.Format("Cipher method '{0}' is not supported.", cipherName)); } - // TODO: Create two specific data types to avoid using SshDataReader class + // TODO: Create two specific data types to avoid using SshDataReader class reader = new SshDataReader(keyData); var decryptedLength = reader.ReadUInt32(); if (decryptedLength > blobSize - 4) + { throw new SshException("Invalid passphrase."); + } if (keyType == "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}") { - var exponent = reader.ReadBigIntWithBits();//e - var d = reader.ReadBigIntWithBits();//d - var modulus = reader.ReadBigIntWithBits();//n - var inverseQ = reader.ReadBigIntWithBits();//u - var q = reader.ReadBigIntWithBits();//p - var p = reader.ReadBigIntWithBits();//q + var exponent = reader.ReadBigIntWithBits(); // e + var d = reader.ReadBigIntWithBits(); // d + var modulus = reader.ReadBigIntWithBits(); // n + var inverseQ = reader.ReadBigIntWithBits(); // u + var q = reader.ReadBigIntWithBits(); // p + var p = reader.ReadBigIntWithBits(); // q _key = new RsaKey(modulus, exponent, d, p, q, inverseQ); HostKey = new KeyHostAlgorithm("ssh-rsa", _key); } @@ -337,13 +350,19 @@ private static byte[] GetCipherKey(string passphrase, int length) private static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string passPhrase, byte[] binarySalt) { if (cipherInfo == null) - throw new ArgumentNullException("cipherInfo"); + { + throw new ArgumentNullException(nameof(cipherInfo)); + } if (cipherData == null) - throw new ArgumentNullException("cipherData"); + { + throw new ArgumentNullException(nameof(cipherData)); + } if (binarySalt == null) - throw new ArgumentNullException("binarySalt"); + { + throw new ArgumentNullException(nameof(binarySalt)); + } var cipherKey = new List(); @@ -351,7 +370,7 @@ private static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, strin { var passwordBytes = Encoding.UTF8.GetBytes(passPhrase); - // Use 8 bytes binary salt + // Use 8 bytes binary salt var initVector = passwordBytes.Concat(binarySalt.Take(8)); var hash = md5.ComputeHash(initVector); @@ -376,12 +395,14 @@ private static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, strin /// /// the key file data (i.e. base64 encoded data between the header/footer) /// passphrase or null if there isn't one - /// + /// + /// The OpenSSH V1 key. + /// private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) { var keyReader = new SshDataReader(keyFileData); - //check magic header + // check magic header var authMagic = Encoding.UTF8.GetBytes("openssh-key-v1\0"); var keyHeaderBytes = keyReader.ReadBytes(authMagic.Length); if (!authMagic.IsEqualTo(keyHeaderBytes)) @@ -389,16 +410,16 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) throw new SshException("This openssh key does not contain the 'openssh-key-v1' format magic header"); } - //cipher will be "aes256-cbc" if using a passphrase, "none" otherwise + // cipher will be "aes256-cbc" if using a passphrase, "none" otherwise var cipherName = keyReader.ReadString(Encoding.UTF8); - //key derivation function (kdf): bcrypt or nothing + // key derivation function (kdf): bcrypt or nothing var kdfName = keyReader.ReadString(Encoding.UTF8); - //kdf options length: 24 if passphrase, 0 if no passphrase + // kdf options length: 24 if passphrase, 0 if no passphrase var kdfOptionsLen = (int)keyReader.ReadUInt32(); byte[] salt = null; - int rounds = 0; + var rounds = 0; if (kdfOptionsLen > 0) { var saltLength = (int)keyReader.ReadUInt32(); @@ -406,21 +427,21 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) rounds = (int)keyReader.ReadUInt32(); } - //number of public keys, only supporting 1 for now + // number of public keys, only supporting 1 for now var numberOfPublicKeys = (int)keyReader.ReadUInt32(); if (numberOfPublicKeys != 1) { throw new SshException("At this time only one public key in the openssh key is supported."); } - //read public key in ssh-format, but we dont need it - keyReader.ReadString(Encoding.UTF8); + // read public key in ssh-format, but we dont need it + _ = keyReader.ReadString(Encoding.UTF8); - //possibly encrypted private key + // possibly encrypted private key var privateKeyLength = (int)keyReader.ReadUInt32(); var privateKeyBytes = keyReader.ReadBytes(privateKeyLength); - //decrypt private key if necessary + // decrypt private key if necessary if (cipherName != "none") { if (string.IsNullOrEmpty(passPhrase)) @@ -433,14 +454,14 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) throw new SshException("kdf " + kdfName + " is not supported for openssh key file"); } - //inspired by the SSHj library (https://github.com/hierynomus/sshj) - //apply the kdf to derive a key and iv from the passphrase + // inspired by the SSHj library (https://github.com/hierynomus/sshj) + // apply the kdf to derive a key and iv from the passphrase var passPhraseBytes = Encoding.UTF8.GetBytes(passPhrase); - byte[] keyiv = new byte[48]; + var keyiv = new byte[48]; new BCrypt().Pbkdf(passPhraseBytes, salt, rounds, keyiv); - byte[] key = new byte[32]; + var key = new byte[32]; Array.Copy(keyiv, 0, key, 0, 32); - byte[] iv = new byte[16]; + var iv = new byte[16]; Array.Copy(keyiv, 32, iv, 0, 16); AesCipher cipher; @@ -459,25 +480,27 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) privateKeyBytes = cipher.Decrypt(privateKeyBytes); } - //validate private key length + // validate private key length privateKeyLength = privateKeyBytes.Length; if (privateKeyLength % 8 != 0) { throw new SshException("The private key section must be a multiple of the block size (8)"); } - //now parse the data we called the private key, it actually contains the public key again - //so we need to parse through it to get the private key bytes, plus there's some - //validation we need to do. + // now parse the data we called the private key, it actually contains the public key again + // so we need to parse through it to get the private key bytes, plus there's some + // validation we need to do. var privateKeyReader = new SshDataReader(privateKeyBytes); - //check ints should match, they wouldn't match for example if the wrong passphrase was supplied - int checkInt1 = (int)privateKeyReader.ReadUInt32(); - int checkInt2 = (int)privateKeyReader.ReadUInt32(); + // check ints should match, they wouldn't match for example if the wrong passphrase was supplied + var checkInt1 = (int) privateKeyReader.ReadUInt32(); + var checkInt2 = (int) privateKeyReader.ReadUInt32(); if (checkInt1 != checkInt2) + { throw new SshException("The random check bytes of the OpenSSH key do not match (" + checkInt1 + " <->" + checkInt2 + ")."); + } - //key type + // key type var keyType = privateKeyReader.ReadString(Encoding.UTF8); Key parsedKey; @@ -486,9 +509,10 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) switch (keyType) { case "ssh-ed25519": - //public key + // public key publicKey = privateKeyReader.ReadBignum2(); - //private key + + // private key unencryptedPrivateKey = privateKeyReader.ReadBignum2(); parsedKey = new ED25519Key(publicKey.Reverse(), unencryptedPrivateKey); break; @@ -496,21 +520,23 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) case "ecdsa-sha2-nistp384": case "ecdsa-sha2-nistp521": // curve - int len = (int)privateKeyReader.ReadUInt32(); + var len = (int) privateKeyReader.ReadUInt32(); var curve = Encoding.ASCII.GetString(privateKeyReader.ReadBytes(len)); - //public key + + // public key publicKey = privateKeyReader.ReadBignum2(); - //private key + + // private key unencryptedPrivateKey = privateKeyReader.ReadBignum2(); parsedKey = new EcdsaKey(curve, publicKey, unencryptedPrivateKey.TrimLeadingZeros()); break; case "ssh-rsa": - var modulus = privateKeyReader.ReadBignum(); //n - var exponent = privateKeyReader.ReadBignum(); //e - var d = privateKeyReader.ReadBignum(); //d + var modulus = privateKeyReader.ReadBignum(); // n + var exponent = privateKeyReader.ReadBignum(); // e + var d = privateKeyReader.ReadBignum(); // d var inverseQ = privateKeyReader.ReadBignum(); // iqmp - var p = privateKeyReader.ReadBignum(); //p - var q = privateKeyReader.ReadBignum(); //q + var p = privateKeyReader.ReadBignum(); // p + var q = privateKeyReader.ReadBignum(); // q parsedKey = new RsaKey(modulus, exponent, d, p, q, inverseQ); break; default: @@ -519,12 +545,12 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) parsedKey.Comment = privateKeyReader.ReadString(Encoding.UTF8); - //The list of privatekey/comment pairs is padded with the bytes 1, 2, 3, ... - //until the total length is a multiple of the cipher block size. + // The list of privatekey/comment pairs is padded with the bytes 1, 2, 3, ... + // until the total length is a multiple of the cipher block size. var padding = privateKeyReader.ReadBytes(); - for (int i = 0; i < padding.Length; i++) + for (var i = 0; i < padding.Length; i++) { - if ((int)padding[i] != i + 1) + if ((int) padding[i] != i + 1) { throw new SshException("Padding of openssh key format contained wrong byte at position: " + i); } @@ -533,27 +559,25 @@ private Key ParseOpenSshV1Key(byte[] keyFileData, string passPhrase) return parsedKey; } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -569,16 +593,13 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~PrivateKeyFile() { - Dispose(false); + Dispose(disposing: false); } - #endregion - private class SshDataReader : SshData { public SshDataReader(byte[] data) @@ -643,4 +664,4 @@ protected override void SaveData() } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Properties/AssemblyInfo.cs b/src/Renci.SshNet/Properties/AssemblyInfo.cs index 22e4125ce..cde7dcdeb 100644 --- a/src/Renci.SshNet/Properties/AssemblyInfo.cs +++ b/src/Renci.SshNet/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; -using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; [assembly: AssemblyTitle("SSH.NET")] [assembly: Guid("ad816c5e-6f13-4589-9f3e-59523f8b77a4")] diff --git a/src/Renci.SshNet/RemotePathDoubleQuoteTransformation.cs b/src/Renci.SshNet/RemotePathDoubleQuoteTransformation.cs index 70af535a2..e4f5496f2 100644 --- a/src/Renci.SshNet/RemotePathDoubleQuoteTransformation.cs +++ b/src/Renci.SshNet/RemotePathDoubleQuoteTransformation.cs @@ -52,19 +52,24 @@ public string Transform(string path) { if (path == null) { - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); } var transformed = new StringBuilder(path.Length); - transformed.Append('"'); + _ = transformed.Append('"'); + foreach (var c in path) { if (c == '"') - transformed.Append('\\'); - transformed.Append(c); + { + _ = transformed.Append('\\'); + } + + _ = transformed.Append(c); } - transformed.Append('"'); + + _ = transformed.Append('"'); return transformed.ToString(); } diff --git a/src/Renci.SshNet/RemotePathNoneTransformation.cs b/src/Renci.SshNet/RemotePathNoneTransformation.cs index ef51531d3..f7bfbab6a 100644 --- a/src/Renci.SshNet/RemotePathNoneTransformation.cs +++ b/src/Renci.SshNet/RemotePathNoneTransformation.cs @@ -23,7 +23,7 @@ public string Transform(string path) { if (path == null) { - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); } return path; diff --git a/src/Renci.SshNet/RemotePathShellQuoteTransformation.cs b/src/Renci.SshNet/RemotePathShellQuoteTransformation.cs index 5093cafd8..53424286c 100644 --- a/src/Renci.SshNet/RemotePathShellQuoteTransformation.cs +++ b/src/Renci.SshNet/RemotePathShellQuoteTransformation.cs @@ -82,7 +82,7 @@ public string Transform(string path) { if (path == null) { - throw new ArgumentNullException("path"); + throw new ArgumentNullException(nameof(path)); } // result is at least value and (likely) leading/trailing single-quotes @@ -99,42 +99,52 @@ public string Transform(string path) { case ShellQuoteState.Unquoted: // Start quoted string - sb.Append('"'); + _ = sb.Append('"'); break; case ShellQuoteState.Quoted: // Continue quoted string break; case ShellQuoteState.SingleQuoted: // Close single-quoted string - sb.Append('\''); + _ = sb.Append('\''); + // Start quoted string - sb.Append('"'); + _ = sb.Append('"'); + break; + default: break; } + state = ShellQuoteState.Quoted; break; case '!': - // In C-Shell, an exclamatation point can only be protected from shell interpretation - // when escaped by a backslash - // Source: - // https://earthsci.stanford.edu/computing/unix/shell/specialchars.php + /* + * In C-Shell, an exclamatation point can only be protected from shell interpretation + * when escaped by a backslash. + * + * Source: + * https://earthsci.stanford.edu/computing/unix/shell/specialchars.php + */ switch (state) { case ShellQuoteState.Unquoted: - sb.Append('\\'); + _ = sb.Append('\\'); break; case ShellQuoteState.Quoted: // Close quoted string - sb.Append('"'); - sb.Append('\\'); + _ = sb.Append('"'); + _ = sb.Append('\\'); break; case ShellQuoteState.SingleQuoted: // Close single quoted string - sb.Append('\''); - sb.Append('\\'); + _ = sb.Append('\''); + _ = sb.Append('\\'); + break; + default: break; } + state = ShellQuoteState.Unquoted; break; default: @@ -142,23 +152,27 @@ public string Transform(string path) { case ShellQuoteState.Unquoted: // Start single-quoted string - sb.Append('\''); + _ = sb.Append('\''); break; case ShellQuoteState.Quoted: // Close quoted string - sb.Append('"'); + _ = sb.Append('"'); + // Start single-quoted string - sb.Append('\''); + _ = sb.Append('\''); break; case ShellQuoteState.SingleQuoted: // Continue single-quoted string break; + default: + break; } + state = ShellQuoteState.SingleQuoted; break; } - sb.Append(c); + _ = sb.Append(c); } switch (state) @@ -167,17 +181,19 @@ public string Transform(string path) break; case ShellQuoteState.Quoted: // Close quoted string - sb.Append('"'); + _ = sb.Append('"'); break; case ShellQuoteState.SingleQuoted: // Close single-quoted string - sb.Append('\''); + _ = sb.Append('\''); + break; + default: break; } if (sb.Length == 0) { - sb.Append("''"); + _ = sb.Append("''"); } return sb.ToString(); diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj index 2f39c80ec..8ae20a567 100644 --- a/src/Renci.SshNet/Renci.SshNet.csproj +++ b/src/Renci.SshNet/Renci.SshNet.csproj @@ -1,12 +1,7 @@  - true - true false Renci.SshNet - ../Renci.SshNet.snk - 6 - true net462;netstandard2.0;net6.0;net7.0 diff --git a/src/Renci.SshNet/ScpClient.NET.cs b/src/Renci.SshNet/ScpClient.NET.cs index cb23cb695..8ca396e7d 100644 --- a/src/Renci.SshNet/ScpClient.NET.cs +++ b/src/Renci.SshNet/ScpClient.NET.cs @@ -1,9 +1,10 @@ using System; -using Renci.SshNet.Channels; using System.IO; -using Renci.SshNet.Common; using System.Text.RegularExpressions; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + namespace Renci.SshNet { /// @@ -27,7 +28,9 @@ public partial class ScpClient public void Upload(FileInfo fileInfo, string path) { if (fileInfo == null) - throw new ArgumentNullException("fileInfo"); + { + throw new ArgumentNullException(nameof(fileInfo)); + } var posixPath = PosixPath.CreateAbsoluteOrRelativeFilePath(path); @@ -43,6 +46,7 @@ public void Upload(FileInfo fileInfo, string path) { throw SecureExecutionRequestRejectedException(); } + CheckReturnCode(input); using (var source = fileInfo.OpenRead()) @@ -67,11 +71,19 @@ public void Upload(FileInfo fileInfo, string path) public void Upload(DirectoryInfo directoryInfo, string path) { if (directoryInfo == null) - throw new ArgumentNullException("directoryInfo"); + { + throw new ArgumentNullException(nameof(directoryInfo)); + } + if (path == null) - throw new ArgumentNullException("path"); + { + throw new ArgumentNullException(nameof(path)); + } + if (path.Length == 0) - throw new ArgumentException("The path cannot be a zero-length string.", "path"); + { + throw new ArgumentException("The path cannot be a zero-length string.", nameof(path)); + } using (var input = ServiceFactory.CreatePipeStream()) using (var channel = Session.CreateChannelSession()) @@ -107,9 +119,14 @@ public void Upload(DirectoryInfo directoryInfo, string path) public void Download(string filename, FileInfo fileInfo) { if (string.IsNullOrEmpty(filename)) + { throw new ArgumentException("filename"); + } + if (fileInfo == null) - throw new ArgumentNullException("fileInfo"); + { + throw new ArgumentNullException(nameof(fileInfo)); + } using (var input = ServiceFactory.CreatePipeStream()) using (var channel = Session.CreateChannelSession()) @@ -122,6 +139,7 @@ public void Download(string filename, FileInfo fileInfo) { throw SecureExecutionRequestRejectedException(); } + // Send reply SendSuccessConfirmation(channel); @@ -141,9 +159,14 @@ public void Download(string filename, FileInfo fileInfo) public void Download(string directoryName, DirectoryInfo directoryInfo) { if (string.IsNullOrEmpty(directoryName)) + { throw new ArgumentException("directoryName"); + } + if (directoryInfo == null) - throw new ArgumentNullException("directoryInfo"); + { + throw new ArgumentNullException(nameof(directoryInfo)); + } using (var input = ServiceFactory.CreatePipeStream()) using (var channel = Session.CreateChannelSession()) @@ -156,6 +179,7 @@ public void Download(string directoryName, DirectoryInfo directoryInfo) { throw SecureExecutionRequestRejectedException(); } + // Send reply SendSuccessConfirmation(channel); @@ -187,7 +211,7 @@ private void UploadTimes(IChannelSession channel, Stream input, FileSystemInfo f /// The directory to upload. private void UploadDirectoryContent(IChannelSession channel, Stream input, DirectoryInfo directoryInfo) { - // Upload files + // Upload files var files = directoryInfo.GetFiles(); foreach (var file in files) { @@ -199,7 +223,7 @@ private void UploadDirectoryContent(IChannelSession channel, Stream input, Direc } } - // Upload directories + // Upload directories var directories = directoryInfo.GetDirectories(); foreach (var directory in directories) { @@ -237,23 +261,26 @@ private void InternalDownload(IChannelSession channel, Stream input, FileSystemI if (message == "E") { - SendSuccessConfirmation(channel); // Send reply + SendSuccessConfirmation(channel); // Send reply directoryCounter--; currentDirectoryFullName = new DirectoryInfo(currentDirectoryFullName).Parent.FullName; if (directoryCounter == 0) + { break; + } + continue; } var match = DirectoryInfoRe.Match(message); if (match.Success) { - SendSuccessConfirmation(channel); // Send reply + SendSuccessConfirmation(channel); // Send reply - // Read directory + // Read directory var filename = match.Result("${filename}"); DirectoryInfo newDirectoryInfo; @@ -265,7 +292,7 @@ private void InternalDownload(IChannelSession channel, Stream input, FileSystemI } else { - // Don't create directory for first level + // Don't create directory for first level newDirectoryInfo = fileSystemInfo as DirectoryInfo; } @@ -278,16 +305,16 @@ private void InternalDownload(IChannelSession channel, Stream input, FileSystemI match = FileInfoRe.Match(message); if (match.Success) { - // Read file + // Read file SendSuccessConfirmation(channel); // Send reply var length = long.Parse(match.Result("${length}")); var fileName = match.Result("${filename}"); - var fileInfo = fileSystemInfo as FileInfo; - - if (fileInfo == null) + if (fileSystemInfo is not FileInfo fileInfo) + { fileInfo = new FileInfo(Path.Combine(currentDirectoryFullName, fileName)); + } using (var output = fileInfo.OpenWrite()) { @@ -298,14 +325,17 @@ private void InternalDownload(IChannelSession channel, Stream input, FileSystemI fileInfo.LastWriteTime = modifiedTime; if (directoryCounter == 0) + { break; + } + continue; } match = TimestampRe.Match(message); if (match.Success) { - // Read timestamp + // Read timestamp SendSuccessConfirmation(channel); // Send reply var mtime = long.Parse(match.Result("${mtime}")); @@ -320,39 +350,5 @@ private void InternalDownload(IChannelSession channel, Stream input, FileSystemI SendErrorConfirmation(channel, string.Format("\"{0}\" is not valid protocol message.", message)); } } - - /// - /// Return a value indicating whether the specified path is a valid SCP file path. - /// - /// The path to verify. - /// - /// if is a valid SCP file path; otherwise, . - /// - /// - /// To match OpenSSH behavior (introduced as a result of CVE-2018-20685), a file path is considered - /// invalid in any of the following conditions: - /// - /// - /// is a zero-length string. - /// - /// - /// is ".". - /// - /// - /// is "..". - /// - /// - /// contains a forward slash (/). - /// - /// - /// - private static bool IsValidScpFilePath(string path) - { - return path != null && - path.Length != 0 && - path != "." && - path != ".." && - path.IndexOf('/') == -1; - } } } diff --git a/src/Renci.SshNet/ScpClient.cs b/src/Renci.SshNet/ScpClient.cs index d8ad55692..7907bfe7d 100644 --- a/src/Renci.SshNet/ScpClient.cs +++ b/src/Renci.SshNet/ScpClient.cs @@ -1,11 +1,13 @@ using System; -using Renci.SshNet.Channels; -using System.IO; -using Renci.SshNet.Common; -using System.Text.RegularExpressions; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; using System.Net; -using System.Collections.Generic; +using System.Text.RegularExpressions; + +using Renci.SshNet.Channels; +using Renci.SshNet.Common; namespace Renci.SshNet { @@ -29,8 +31,9 @@ namespace Renci.SshNet /// public partial class ScpClient : BaseClient { + private const string Message = "filename"; private static readonly Regex FileInfoRe = new Regex(@"C(?\d{4}) (?\d+) (?.+)"); - private static readonly byte[] SuccessConfirmationCode = {0}; + private static readonly byte[] SuccessConfirmationCode = { 0 }; private static readonly byte[] ErrorConfirmationCode = { 1 }; private IRemotePathTransformation _remotePathTransformation; @@ -56,7 +59,7 @@ public partial class ScpClient : BaseClient /// Gets or sets the transformation to apply to remote paths. /// /// - /// The transformation to apply to remote paths. The default is . + /// The transformation to apply to remote paths. The default is . /// /// is null. /// @@ -75,7 +78,10 @@ public IRemotePathTransformation RemotePathTransformation set { if (value == null) - throw new ArgumentNullException("value"); + { + throw new ArgumentNullException(nameof(value)); + } + _remotePathTransformation = value; } } @@ -90,15 +96,13 @@ public IRemotePathTransformation RemotePathTransformation /// public event EventHandler Uploading; - #region Constructors - /// /// Initializes a new instance of the class. /// /// The connection info. /// is null. public ScpClient(ConnectionInfo connectionInfo) - : this(connectionInfo, false) + : this(connectionInfo, ownsConnectionInfo: false) { } @@ -114,7 +118,7 @@ public ScpClient(ConnectionInfo connectionInfo) /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public ScpClient(string host, int port, string username, string password) - : this(new PasswordConnectionInfo(host, port, username, password), true) + : this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true) { } @@ -143,7 +147,7 @@ public ScpClient(string host, string username, string password) /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public ScpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) - : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) + : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true) { } @@ -195,8 +199,6 @@ internal ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServ _remotePathTransformation = serviceFactory.CreateRemotePathDoubleQuoteTransformation(); } - #endregion - /// /// Uploads the specified stream to the remote host. /// @@ -222,6 +224,7 @@ public void Upload(Stream source, string path) { throw SecureExecutionRequestRejectedException(); } + CheckReturnCode(input); UploadFileModeAndName(channel, input, source.Length, posixPath.File); @@ -241,10 +244,14 @@ public void Upload(Stream source, string path) public void Download(string filename, Stream destination) { if (filename.IsNullOrWhiteSpace()) - throw new ArgumentException("filename"); + { + throw new ArgumentException(Message); + } if (destination == null) - throw new ArgumentNullException("destination"); + { + throw new ArgumentNullException(nameof(destination)); + } using (var input = ServiceFactory.CreatePipeStream()) using (var channel = Session.CreateChannelSession()) @@ -252,22 +259,23 @@ public void Download(string filename, Stream destination) channel.DataReceived += (sender, e) => input.Write(e.Data, 0, e.Data.Length); channel.Open(); - // Send channel command request - if (!channel.SendExecRequest(string.Format("scp -f {0}", _remotePathTransformation.Transform(filename)))) + // Send channel command request + if (!channel.SendExecRequest(string.Concat("scp -f ", _remotePathTransformation.Transform(filename)))) { throw SecureExecutionRequestRejectedException(); } - SendSuccessConfirmation(channel); // Send reply + + SendSuccessConfirmation(channel); // Send reply var message = ReadString(input); var match = FileInfoRe.Match(message); if (match.Success) { - // Read file + // Read file SendSuccessConfirmation(channel); // Send reply - var length = long.Parse(match.Result("${length}")); + var length = long.Parse(match.Result("${length}"), CultureInfo.InvariantCulture); var fileName = match.Result("${filename}"); InternalDownload(channel, input, destination, fileName, length); @@ -364,18 +372,12 @@ private void InternalDownload(IChannel channel, Stream input, Stream output, str private void RaiseDownloadingEvent(string filename, long size, long downloaded) { - if (Downloading != null) - { - Downloading(this, new ScpDownloadEventArgs(filename, size, downloaded)); - } + Downloading?.Invoke(this, new ScpDownloadEventArgs(filename, size, downloaded)); } private void RaiseUploadingEvent(string filename, long size, long uploaded) { - if (Uploading != null) - { - Uploading(this, new ScpUploadEventArgs(filename, size, uploaded)); - } + Uploading?.Invoke(this, new ScpUploadEventArgs(filename, size, uploaded)); } private static void SendSuccessConfirmation(IChannel channel) @@ -423,8 +425,12 @@ private static void SendData(IChannel channel, byte[] buffer) private static int ReadByte(Stream stream) { var b = stream.ReadByte(); + if (b == -1) + { throw new SshException("Stream has been closed."); + } + return b; } @@ -442,7 +448,7 @@ private string ReadString(Stream stream) var buffer = new List(); var b = ReadByte(stream); - if (b == 1 || b == 2) + if (b is 1 or 2) { hasError = true; b = ReadByte(stream); @@ -457,7 +463,10 @@ private string ReadString(Stream stream) var readBytes = buffer.ToArray(); if (hasError) + { throw new ScpException(ConnectionInfo.Encoding.GetString(readBytes, 0, readBytes.Length)); + } + return ConnectionInfo.Encoding.GetString(readBytes, 0, readBytes.Length); } @@ -466,4 +475,4 @@ private static SshException SecureExecutionRequestRejectedException() throw new SshException("Secure copy execution request was rejected by the server. Please consult the server logs."); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/BouncyCastle/.editorconfig b/src/Renci.SshNet/Security/BouncyCastle/.editorconfig new file mode 100644 index 000000000..265666760 --- /dev/null +++ b/src/Renci.SshNet/Security/BouncyCastle/.editorconfig @@ -0,0 +1,7 @@ +[*.cs] + +generated_code = true + +# IDE0005: Remove unnecessary using directives +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 +dotnet_diagnostic.IDE0005.severity = none diff --git a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs index 5bb0c3540..57e49ea71 100644 --- a/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs +++ b/src/Renci.SshNet/Security/BouncyCastle/crypto/prng/IRandomGenerator.cs @@ -23,4 +23,4 @@ internal interface IRandomGenerator /// Length of segment to fill. void NextBytes(byte[] bytes, int start, int len); } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs b/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs index 143a369b3..acfae5264 100644 --- a/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs +++ b/src/Renci.SshNet/Security/BouncyCastle/math/ec/endo/GlvEndomorphism.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Security.Org.BouncyCastle.Math.EC.Endo { internal interface GlvEndomorphism - : ECEndomorphism + : ECEndomorphism { BigInteger[] DecomposeScalar(BigInteger k); } diff --git a/src/Renci.SshNet/Security/Chaos.NaCl/.editorconfig b/src/Renci.SshNet/Security/Chaos.NaCl/.editorconfig new file mode 100644 index 000000000..265666760 --- /dev/null +++ b/src/Renci.SshNet/Security/Chaos.NaCl/.editorconfig @@ -0,0 +1,7 @@ +[*.cs] + +generated_code = true + +# IDE0005: Remove unnecessary using directives +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 +dotnet_diagnostic.IDE0005.severity = none diff --git a/src/Renci.SshNet/Security/Cryptography/.editorconfig b/src/Renci.SshNet/Security/Cryptography/.editorconfig new file mode 100644 index 000000000..7e36b6e59 --- /dev/null +++ b/src/Renci.SshNet/Security/Cryptography/.editorconfig @@ -0,0 +1,12 @@ +[Bcrypt.cs] + +generated_code = true + +# IDE0005: Remove unnecessary using directives +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0005 +dotnet_diagnostic.IDE0005.severity = none + +# IDE0007: Use var instead of explicit type +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0007-ide0008 +# +dotnet_diagnostic.IDE0007.severity = none \ No newline at end of file diff --git a/src/Renci.SshNet/Security/Cryptography/BlockCipher.cs b/src/Renci.SshNet/Security/Cryptography/BlockCipher.cs index 18cf81cb6..17e14c5dc 100644 --- a/src/Renci.SshNet/Security/Cryptography/BlockCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/BlockCipher.cs @@ -135,6 +135,7 @@ public override byte[] Decrypt(byte[] data, int offset, int length) { throw new ArgumentException("data"); } + data = _padding.Pad(_blockSize, data, offset, length); offset = 0; length = data.Length; diff --git a/src/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs index 752f97014..7312a6292 100644 --- a/src/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs @@ -19,7 +19,9 @@ public abstract class CipherDigitalSignature : DigitalSignature protected CipherDigitalSignature(ObjectIdentifier oid, AsymmetricCipher cipher) { if (cipher == null) - throw new ArgumentNullException("cipher"); + { + throw new ArgumentNullException(nameof(cipher)); + } _cipher = cipher; _oid = oid; @@ -50,10 +52,10 @@ public override bool Verify(byte[] input, byte[] signature) /// public override byte[] Sign(byte[] input) { - // Calculate hash value + // Calculate hash value var hashData = Hash(input); - // Calculate DER string + // Calculate DER string var derEncodedHash = DerEncode(hashData); return _cipher.Encrypt(derEncodedHash).TrimLeadingZeros(); @@ -70,7 +72,9 @@ public override byte[] Sign(byte[] input) /// Encodes hash using DER. /// /// The hash data. - /// DER Encoded byte array + /// + /// DER Encoded byte array. + /// protected byte[] DerEncode(byte[] hashData) { var alg = new DerData(); diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs index b42258624..9fb8d0a25 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs @@ -569,8 +569,10 @@ public AesCipher(byte[] key, CipherMode mode, CipherPadding padding) { var keySize = key.Length * 8; - if (!(keySize == 256 || keySize == 192 || keySize == 128)) + if (keySize is not (256 or 192 or 128)) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "KeySize '{0}' is not valid for this algorithm.", keySize)); + } } /// @@ -589,10 +591,14 @@ public AesCipher(byte[] key, CipherMode mode, CipherPadding padding) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer == null) - throw new ArgumentNullException("inputBuffer"); + { + throw new ArgumentNullException(nameof(inputBuffer)); + } if (outputBuffer == null) - throw new ArgumentNullException("outputBuffer"); + { + throw new ArgumentNullException(nameof(outputBuffer)); + } if ((inputOffset + (32 / 2)) > inputBuffer.Length) { @@ -604,10 +610,7 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC throw new IndexOutOfRangeException("output buffer too short"); } - if (_encryptionKey == null) - { - _encryptionKey = GenerateWorkingKey(true, Key); - } + _encryptionKey ??= GenerateWorkingKey(true, Key); UnPackBlock(inputBuffer, inputOffset); @@ -634,10 +637,14 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer == null) - throw new ArgumentNullException("inputBuffer"); + { + throw new ArgumentNullException(nameof(inputBuffer)); + } if (outputBuffer == null) - throw new ArgumentNullException("outputBuffer"); + { + throw new ArgumentNullException(nameof(outputBuffer)); + } if ((inputOffset + (32 / 2)) > inputBuffer.Length) { @@ -649,10 +656,7 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC throw new IndexOutOfRangeException("output buffer too short"); } - if (_decryptionKey == null) - { - _decryptionKey = GenerateWorkingKey(false, Key); - } + _decryptionKey ??= GenerateWorkingKey(false, Key); UnPackBlock(inputBuffer, inputOffset); @@ -668,7 +672,9 @@ private uint[] GenerateWorkingKey(bool isEncryption, byte[] key) int KC = key.Length / 4; // key length in words if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length)) + { throw new ArgumentException("Key length not 128/192/256 bits."); + } _rounds = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes uint[] W = new uint[(_rounds + 1) * 4]; // 4 words in a block @@ -679,7 +685,7 @@ private uint[] GenerateWorkingKey(bool isEncryption, byte[] key) int t = 0; - for (int i = 0; i < key.Length; t++) + for (var i = 0; i < key.Length; t++) { W[(t >> 2) * 4 + (t & 3)] = Pack.LittleEndianToUInt32(key, i); i += 4; diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs index 0707ce2e2..831b7f3cc 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs @@ -151,6 +151,7 @@ private int ProcessBytes(byte[] inputBuffer, int inputOffset, int inputCount, by // xor outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ _engineState[(_engineState[_x] + _engineState[_y]) & 0xff]); } + return inputCount; } @@ -161,10 +162,7 @@ private void SetKey(byte[] keyBytes) _x = 0; _y = 0; - if (_engineState == null) - { - _engineState = new byte[STATE_LENGTH]; - } + _engineState ??= new byte[STATE_LENGTH]; // reset the state of the engine for (var i = 0; i < STATE_LENGTH; i++) @@ -178,6 +176,7 @@ private void SetKey(byte[] keyBytes) for (var i = 0; i < STATE_LENGTH; i++) { i2 = ((keyBytes[i1] & 0xff) + _engineState[i] + i2) & 0xff; + // do the byte-swap inline var tmp = _engineState[i]; _engineState[i] = _engineState[i2]; diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs index d68d39886..2dfa7909e 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs @@ -348,7 +348,9 @@ public BlowfishCipher(byte[] key, CipherMode mode, CipherPadding padding) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputCount != BlockSize) + { throw new ArgumentException("inputCount"); + } uint xl = Pack.BigEndianToUInt32(inputBuffer, inputOffset); uint xr = Pack.BigEndianToUInt32(inputBuffer, inputOffset + 4); @@ -451,6 +453,7 @@ private void SetKey(byte[] key) keyIndex = 0; } } + // XOR the newly created 32 bit chunk onto the P-array _p[i] ^= data; } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs index 1f6a2aa95..1fbe5bc4b 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs @@ -12,8 +12,6 @@ public class DesCipher : BlockCipher private int[] _decryptionKey; - #region Static tables - private static readonly short[] Bytebit = {128, 64, 32, 16, 8, 4, 2, 1}; private static readonly int[] Bigbyte = @@ -212,8 +210,6 @@ public class DesCipher : BlockCipher 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; - #endregion - /// /// Initializes a new instance of the class. /// @@ -240,16 +236,17 @@ public DesCipher(byte[] key, CipherMode mode, CipherPadding padding) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if ((inputOffset + BlockSize) > inputBuffer.Length) + { throw new IndexOutOfRangeException("input buffer too short"); + } if ((outputOffset + BlockSize) > outputBuffer.Length) - throw new IndexOutOfRangeException("output buffer too short"); - - if (_encryptionKey == null) { - _encryptionKey = GenerateWorkingKey(true, Key); + throw new IndexOutOfRangeException("output buffer too short"); } + _encryptionKey ??= GenerateWorkingKey(true, Key); + DesFunc(_encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset); return BlockSize; @@ -269,16 +266,17 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if ((inputOffset + BlockSize) > inputBuffer.Length) + { throw new IndexOutOfRangeException("input buffer too short"); + } if ((outputOffset + BlockSize) > outputBuffer.Length) - throw new IndexOutOfRangeException("output buffer too short"); - - if (_decryptionKey == null) { - _decryptionKey = GenerateWorkingKey(false, Key); + throw new IndexOutOfRangeException("output buffer too short"); } + _decryptionKey ??= GenerateWorkingKey(false, Key); + DesFunc(_decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset); return BlockSize; @@ -294,18 +292,18 @@ protected int[] GenerateWorkingKey(bool encrypting, byte[] key) { ValidateKey(); - int[] newKey = new int[32]; - bool[] pc1m = new bool[56]; - bool[] pcr = new bool[56]; + var newKey = new int[32]; + var pc1m = new bool[56]; + var pcr = new bool[56]; - for (int j = 0; j < 56; j++) + for (var j = 0; j < 56; j++) { int l = Pc1[j]; pc1m[j] = ((key[(uint)l >> 3] & Bytebit[l & 07]) != 0); } - for (int i = 0; i < 16; i++) + for (var i = 0; i < 16; i++) { int l, m; @@ -321,7 +319,7 @@ protected int[] GenerateWorkingKey(bool encrypting, byte[] key) var n = m + 1; newKey[m] = newKey[n] = 0; - for (int j = 0; j < 28; j++) + for (var j = 0; j < 28; j++) { l = j + Totrot[i]; if (l < 28) @@ -334,7 +332,7 @@ protected int[] GenerateWorkingKey(bool encrypting, byte[] key) } } - for (int j = 28; j < 56; j++) + for (var j = 28; j < 56; j++) { l = j + Totrot[i]; if (l < 56) @@ -347,7 +345,7 @@ protected int[] GenerateWorkingKey(bool encrypting, byte[] key) } } - for (int j = 0; j < 24; j++) + for (var j = 0; j < 24; j++) { if (pcr[Pc2[j]]) { @@ -364,7 +362,7 @@ protected int[] GenerateWorkingKey(bool encrypting, byte[] key) // // store the processed key // - for (int i = 0; i != 32; i += 2) + for (var i = 0; i != 32; i += 2) { var i1 = newKey[i]; var i2 = newKey[i + 1]; @@ -391,7 +389,9 @@ protected virtual void ValidateKey() var keySize = Key.Length * 8; if (keySize != 64) + { throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize)); + } } /// @@ -409,16 +409,16 @@ protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outByt var work = ((left >> 4) ^ right) & 0x0f0f0f0f; right ^= work; - left ^= (work << 4); + left ^= work << 4; work = ((left >> 16) ^ right) & 0x0000ffff; right ^= work; - left ^= (work << 16); + left ^= work << 16; work = ((right >> 2) ^ left) & 0x33333333; left ^= work; - right ^= (work << 2); + right ^= work << 2; work = ((right >> 8) ^ left) & 0x00ff00ff; left ^= work; - right ^= (work << 8); + right ^= work << 8; right = (right << 1) | (right >> 31); work = (left ^ right) & 0xaaaaaaaa; left ^= work; @@ -460,16 +460,16 @@ protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outByt left = (left << 31) | (left >> 1); work = ((left >> 8) ^ right) & 0x00ff00ff; right ^= work; - left ^= (work << 8); + left ^= work << 8; work = ((left >> 2) ^ right) & 0x33333333; right ^= work; - left ^= (work << 2); + left ^= work << 2; work = ((right >> 16) ^ left) & 0x0000ffff; left ^= work; - right ^= (work << 16); + right ^= work << 16; work = ((right >> 4) ^ left) & 0x0f0f0f0f; left ^= work; - right ^= (work << 4); + right ^= work << 4; Pack.UInt32ToBigEndian(right, outBytes, outOff); Pack.UInt32ToBigEndian(left, outBytes, outOff + 4); diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs index c6ac2f0ab..de07141c3 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs @@ -31,20 +31,26 @@ public CbcCipherMode(byte[] iv) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { IV[i] ^= inputBuffer[inputOffset + i]; } - Cipher.EncryptBlock(IV, 0, inputCount, outputBuffer, outputOffset); + _ = Cipher.EncryptBlock(IV, 0, inputCount, outputBuffer, outputOffset); Buffer.BlockCopy(outputBuffer, outputOffset, IV, 0, IV.Length); @@ -65,17 +71,23 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset); + _ = Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] ^= IV[i]; } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs index 3171e2bbc..ae889e875 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs @@ -34,17 +34,23 @@ public CfbCipherMode(byte[] iv) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } @@ -69,20 +75,26 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); Buffer.BlockCopy(IV, _blockSize, IV, 0, IV.Length - _blockSize); Buffer.BlockCopy(inputBuffer, inputOffset, IV, IV.Length - _blockSize, _blockSize); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs index cbe5d7e60..47146567b 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs @@ -34,22 +34,28 @@ public CtrCipherMode(byte[] iv) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } - int j = IV.Length; + var j = IV.Length; while (--j >= 0 && ++IV[j] == 0) ; return _blockSize; @@ -69,22 +75,28 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } - int j = IV.Length; + var j = IV.Length; while (--j >= 0 && ++IV[j] == 0) ; return _blockSize; diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs index a13cfb0a1..1f321f454 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs @@ -34,17 +34,23 @@ public OfbCipherMode(byte[] iv) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } @@ -69,17 +75,23 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputBuffer.Length - inputOffset < _blockSize) + { throw new ArgumentException("Invalid input buffer"); + } if (outputBuffer.Length - outputOffset < _blockSize) + { throw new ArgumentException("Invalid output buffer"); + } if (inputCount != _blockSize) + { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize)); + } - Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); + _ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0); - for (int i = 0; i < _blockSize; i++) + for (var i = 0; i < _blockSize; i++) { outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]); } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs index 70d94c20f..18e85c597 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings { /// - /// Implements PKCS5 cipher padding + /// Implements PKCS5 cipher padding. /// public class PKCS5Padding : CipherPadding { @@ -37,10 +37,12 @@ public override byte[] Pad(byte[] input, int offset, int length, int paddingleng { var output = new byte[length + paddinglength]; Buffer.BlockCopy(input, offset, output, 0, length); + for (var i = 0; i < paddinglength; i++) { output[length + i] = (byte) paddinglength; } + return output; } } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs index 2623d8fd0..cfe0ae9a3 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs @@ -37,10 +37,12 @@ public override byte[] Pad(byte[] input, int offset, int length, int paddingleng { var output = new byte[length + paddinglength]; Buffer.BlockCopy(input, offset, output, 0, length); + for (var i = 0; i < paddinglength; i++) { output[length + i] = (byte) paddinglength; } + return output; } } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs index 116471bde..0bfce1aad 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs @@ -19,7 +19,9 @@ public class RsaCipher : AsymmetricCipher public RsaCipher(RsaKey key) { if (key == null) - throw new ArgumentNullException("key"); + { + throw new ArgumentNullException(nameof(key)); + } _key = key; _isPrivate = !_key.D.IsZero; @@ -34,7 +36,7 @@ public RsaCipher(RsaKey key) /// Encrypted data. public override byte[] Encrypt(byte[] data, int offset, int length) { - // Calculate signature + // Calculate signature var bitLength = _key.Modulus.BitLength; var paddedBlock = new byte[bitLength / 8 + (bitLength % 8 > 0 ? 1 : 0) - 1]; @@ -79,12 +81,18 @@ public override byte[] Decrypt(byte[] data, int offset, int length) { var paddedBlock = Transform(data, offset, length); - if (paddedBlock[0] != 1 && paddedBlock[0] != 2) + if (paddedBlock[0] is not 1 and not 2) + { throw new NotSupportedException("Only block type 01 or 02 are supported."); + } var position = 1; + while (position < paddedBlock.Length && paddedBlock[position] != 0) + { position++; + } + position++; var result = new byte[paddedBlock.Length - position]; @@ -115,28 +123,30 @@ private byte[] Transform(byte[] data, int offset, int length) var bitLength = _key.Modulus.BitLength; if (max < BigInteger.One) + { throw new SshException("Invalid RSA key."); + } while (random <= BigInteger.One || random >= max) { random = BigInteger.Random(bitLength); } - var blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, _key.Exponent, _key.Modulus) * input), _key.Modulus); + var blindedInput = BigInteger.PositiveMod(BigInteger.ModPow(random, _key.Exponent, _key.Modulus) * input, _key.Modulus); // mP = ((input Mod p) ^ dP)) Mod p - var mP = BigInteger.ModPow((blindedInput % _key.P), _key.DP, _key.P); + var mP = BigInteger.ModPow(blindedInput % _key.P, _key.DP, _key.P); // mQ = ((input Mod q) ^ dQ)) Mod q - var mQ = BigInteger.ModPow((blindedInput % _key.Q), _key.DQ, _key.Q); + var mQ = BigInteger.ModPow(blindedInput % _key.Q, _key.DQ, _key.Q); - var h = BigInteger.PositiveMod(((mP - mQ) * _key.InverseQ), _key.P); + var h = BigInteger.PositiveMod((mP - mQ) * _key.InverseQ, _key.P); var m = h * _key.Q + mQ; var rInv = BigInteger.ModInverse(random, _key.Modulus); - result = BigInteger.PositiveMod((m * rInv), _key.Modulus); + result = BigInteger.PositiveMod(m * rInv, _key.Modulus); } else { diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs index 613059467..0f67ac204 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs @@ -11,7 +11,12 @@ public sealed class SerpentCipher : BlockCipher private const int Phi = unchecked((int)0x9E3779B9); // (Sqrt(5) - 1) * 2**31 private readonly int[] _workingKey; - private int _x0, _x1, _x2, _x3; // registers + + // registers + private int _x0; + private int _x1; + private int _x2; + private int _x3; /// /// Initializes a new instance of the class. @@ -26,8 +31,10 @@ public SerpentCipher(byte[] key, CipherMode mode, CipherPadding padding) { var keySize = key.Length * 8; - if (!(keySize == 128 || keySize == 192 || keySize == 256)) + if (keySize is not (128 or 192 or 256)) + { throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize)); + } _workingKey = MakeWorkingKey(key); } @@ -46,44 +53,77 @@ public SerpentCipher(byte[] key, CipherMode mode, CipherPadding padding) public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputCount != BlockSize) + { throw new ArgumentException("inputCount"); + } _x3 = BytesToWord(inputBuffer, inputOffset); _x2 = BytesToWord(inputBuffer, inputOffset + 4); _x1 = BytesToWord(inputBuffer, inputOffset + 8); _x0 = BytesToWord(inputBuffer, inputOffset + 12); - Sb0(_workingKey[0] ^ _x0, _workingKey[1] ^ _x1, _workingKey[2] ^ _x2, _workingKey[3] ^ _x3); LT(); - Sb1(_workingKey[4] ^ _x0, _workingKey[5] ^ _x1, _workingKey[6] ^ _x2, _workingKey[7] ^ _x3); LT(); - Sb2(_workingKey[8] ^ _x0, _workingKey[9] ^ _x1, _workingKey[10] ^ _x2, _workingKey[11] ^ _x3); LT(); - Sb3(_workingKey[12] ^ _x0, _workingKey[13] ^ _x1, _workingKey[14] ^ _x2, _workingKey[15] ^ _x3); LT(); - Sb4(_workingKey[16] ^ _x0, _workingKey[17] ^ _x1, _workingKey[18] ^ _x2, _workingKey[19] ^ _x3); LT(); - Sb5(_workingKey[20] ^ _x0, _workingKey[21] ^ _x1, _workingKey[22] ^ _x2, _workingKey[23] ^ _x3); LT(); - Sb6(_workingKey[24] ^ _x0, _workingKey[25] ^ _x1, _workingKey[26] ^ _x2, _workingKey[27] ^ _x3); LT(); - Sb7(_workingKey[28] ^ _x0, _workingKey[29] ^ _x1, _workingKey[30] ^ _x2, _workingKey[31] ^ _x3); LT(); - Sb0(_workingKey[32] ^ _x0, _workingKey[33] ^ _x1, _workingKey[34] ^ _x2, _workingKey[35] ^ _x3); LT(); - Sb1(_workingKey[36] ^ _x0, _workingKey[37] ^ _x1, _workingKey[38] ^ _x2, _workingKey[39] ^ _x3); LT(); - Sb2(_workingKey[40] ^ _x0, _workingKey[41] ^ _x1, _workingKey[42] ^ _x2, _workingKey[43] ^ _x3); LT(); - Sb3(_workingKey[44] ^ _x0, _workingKey[45] ^ _x1, _workingKey[46] ^ _x2, _workingKey[47] ^ _x3); LT(); - Sb4(_workingKey[48] ^ _x0, _workingKey[49] ^ _x1, _workingKey[50] ^ _x2, _workingKey[51] ^ _x3); LT(); - Sb5(_workingKey[52] ^ _x0, _workingKey[53] ^ _x1, _workingKey[54] ^ _x2, _workingKey[55] ^ _x3); LT(); - Sb6(_workingKey[56] ^ _x0, _workingKey[57] ^ _x1, _workingKey[58] ^ _x2, _workingKey[59] ^ _x3); LT(); - Sb7(_workingKey[60] ^ _x0, _workingKey[61] ^ _x1, _workingKey[62] ^ _x2, _workingKey[63] ^ _x3); LT(); - Sb0(_workingKey[64] ^ _x0, _workingKey[65] ^ _x1, _workingKey[66] ^ _x2, _workingKey[67] ^ _x3); LT(); - Sb1(_workingKey[68] ^ _x0, _workingKey[69] ^ _x1, _workingKey[70] ^ _x2, _workingKey[71] ^ _x3); LT(); - Sb2(_workingKey[72] ^ _x0, _workingKey[73] ^ _x1, _workingKey[74] ^ _x2, _workingKey[75] ^ _x3); LT(); - Sb3(_workingKey[76] ^ _x0, _workingKey[77] ^ _x1, _workingKey[78] ^ _x2, _workingKey[79] ^ _x3); LT(); - Sb4(_workingKey[80] ^ _x0, _workingKey[81] ^ _x1, _workingKey[82] ^ _x2, _workingKey[83] ^ _x3); LT(); - Sb5(_workingKey[84] ^ _x0, _workingKey[85] ^ _x1, _workingKey[86] ^ _x2, _workingKey[87] ^ _x3); LT(); - Sb6(_workingKey[88] ^ _x0, _workingKey[89] ^ _x1, _workingKey[90] ^ _x2, _workingKey[91] ^ _x3); LT(); - Sb7(_workingKey[92] ^ _x0, _workingKey[93] ^ _x1, _workingKey[94] ^ _x2, _workingKey[95] ^ _x3); LT(); - Sb0(_workingKey[96] ^ _x0, _workingKey[97] ^ _x1, _workingKey[98] ^ _x2, _workingKey[99] ^ _x3); LT(); - Sb1(_workingKey[100] ^ _x0, _workingKey[101] ^ _x1, _workingKey[102] ^ _x2, _workingKey[103] ^ _x3); LT(); - Sb2(_workingKey[104] ^ _x0, _workingKey[105] ^ _x1, _workingKey[106] ^ _x2, _workingKey[107] ^ _x3); LT(); - Sb3(_workingKey[108] ^ _x0, _workingKey[109] ^ _x1, _workingKey[110] ^ _x2, _workingKey[111] ^ _x3); LT(); - Sb4(_workingKey[112] ^ _x0, _workingKey[113] ^ _x1, _workingKey[114] ^ _x2, _workingKey[115] ^ _x3); LT(); - Sb5(_workingKey[116] ^ _x0, _workingKey[117] ^ _x1, _workingKey[118] ^ _x2, _workingKey[119] ^ _x3); LT(); - Sb6(_workingKey[120] ^ _x0, _workingKey[121] ^ _x1, _workingKey[122] ^ _x2, _workingKey[123] ^ _x3); LT(); + Sb0(_workingKey[0] ^ _x0, _workingKey[1] ^ _x1, _workingKey[2] ^ _x2, _workingKey[3] ^ _x3); + LT(); + Sb1(_workingKey[4] ^ _x0, _workingKey[5] ^ _x1, _workingKey[6] ^ _x2, _workingKey[7] ^ _x3); + LT(); + Sb2(_workingKey[8] ^ _x0, _workingKey[9] ^ _x1, _workingKey[10] ^ _x2, _workingKey[11] ^ _x3); + LT(); + Sb3(_workingKey[12] ^ _x0, _workingKey[13] ^ _x1, _workingKey[14] ^ _x2, _workingKey[15] ^ _x3); + LT(); + Sb4(_workingKey[16] ^ _x0, _workingKey[17] ^ _x1, _workingKey[18] ^ _x2, _workingKey[19] ^ _x3); + LT(); + Sb5(_workingKey[20] ^ _x0, _workingKey[21] ^ _x1, _workingKey[22] ^ _x2, _workingKey[23] ^ _x3); + LT(); + Sb6(_workingKey[24] ^ _x0, _workingKey[25] ^ _x1, _workingKey[26] ^ _x2, _workingKey[27] ^ _x3); + LT(); + Sb7(_workingKey[28] ^ _x0, _workingKey[29] ^ _x1, _workingKey[30] ^ _x2, _workingKey[31] ^ _x3); + LT(); + Sb0(_workingKey[32] ^ _x0, _workingKey[33] ^ _x1, _workingKey[34] ^ _x2, _workingKey[35] ^ _x3); + LT(); + Sb1(_workingKey[36] ^ _x0, _workingKey[37] ^ _x1, _workingKey[38] ^ _x2, _workingKey[39] ^ _x3); + LT(); + Sb2(_workingKey[40] ^ _x0, _workingKey[41] ^ _x1, _workingKey[42] ^ _x2, _workingKey[43] ^ _x3); + LT(); + Sb3(_workingKey[44] ^ _x0, _workingKey[45] ^ _x1, _workingKey[46] ^ _x2, _workingKey[47] ^ _x3); + LT(); + Sb4(_workingKey[48] ^ _x0, _workingKey[49] ^ _x1, _workingKey[50] ^ _x2, _workingKey[51] ^ _x3); + LT(); + Sb5(_workingKey[52] ^ _x0, _workingKey[53] ^ _x1, _workingKey[54] ^ _x2, _workingKey[55] ^ _x3); + LT(); + Sb6(_workingKey[56] ^ _x0, _workingKey[57] ^ _x1, _workingKey[58] ^ _x2, _workingKey[59] ^ _x3); + LT(); + Sb7(_workingKey[60] ^ _x0, _workingKey[61] ^ _x1, _workingKey[62] ^ _x2, _workingKey[63] ^ _x3); + LT(); + Sb0(_workingKey[64] ^ _x0, _workingKey[65] ^ _x1, _workingKey[66] ^ _x2, _workingKey[67] ^ _x3); + LT(); + Sb1(_workingKey[68] ^ _x0, _workingKey[69] ^ _x1, _workingKey[70] ^ _x2, _workingKey[71] ^ _x3); + LT(); + Sb2(_workingKey[72] ^ _x0, _workingKey[73] ^ _x1, _workingKey[74] ^ _x2, _workingKey[75] ^ _x3); + LT(); + Sb3(_workingKey[76] ^ _x0, _workingKey[77] ^ _x1, _workingKey[78] ^ _x2, _workingKey[79] ^ _x3); + LT(); + Sb4(_workingKey[80] ^ _x0, _workingKey[81] ^ _x1, _workingKey[82] ^ _x2, _workingKey[83] ^ _x3); + LT(); + Sb5(_workingKey[84] ^ _x0, _workingKey[85] ^ _x1, _workingKey[86] ^ _x2, _workingKey[87] ^ _x3); + LT(); + Sb6(_workingKey[88] ^ _x0, _workingKey[89] ^ _x1, _workingKey[90] ^ _x2, _workingKey[91] ^ _x3); + LT(); + Sb7(_workingKey[92] ^ _x0, _workingKey[93] ^ _x1, _workingKey[94] ^ _x2, _workingKey[95] ^ _x3); + LT(); + Sb0(_workingKey[96] ^ _x0, _workingKey[97] ^ _x1, _workingKey[98] ^ _x2, _workingKey[99] ^ _x3); + LT(); + Sb1(_workingKey[100] ^ _x0, _workingKey[101] ^ _x1, _workingKey[102] ^ _x2, _workingKey[103] ^ _x3); + LT(); + Sb2(_workingKey[104] ^ _x0, _workingKey[105] ^ _x1, _workingKey[106] ^ _x2, _workingKey[107] ^ _x3); + LT(); + Sb3(_workingKey[108] ^ _x0, _workingKey[109] ^ _x1, _workingKey[110] ^ _x2, _workingKey[111] ^ _x3); + LT(); + Sb4(_workingKey[112] ^ _x0, _workingKey[113] ^ _x1, _workingKey[114] ^ _x2, _workingKey[115] ^ _x3); + LT(); + Sb5(_workingKey[116] ^ _x0, _workingKey[117] ^ _x1, _workingKey[118] ^ _x2, _workingKey[119] ^ _x3); + LT(); + Sb6(_workingKey[120] ^ _x0, _workingKey[121] ^ _x1, _workingKey[122] ^ _x2, _workingKey[123] ^ _x3); + LT(); Sb7(_workingKey[124] ^ _x0, _workingKey[125] ^ _x1, _workingKey[126] ^ _x2, _workingKey[127] ^ _x3); WordToBytes(_workingKey[131] ^ _x3, outputBuffer, outputOffset); @@ -108,7 +148,9 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if (inputCount != BlockSize) + { throw new ArgumentException("inputCount"); + } _x3 = _workingKey[131] ^ BytesToWord(inputBuffer, inputOffset); _x2 = _workingKey[130] ^ BytesToWord(inputBuffer, inputOffset + 4); @@ -116,68 +158,253 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC _x0 = _workingKey[128] ^ BytesToWord(inputBuffer, inputOffset + 12); Ib7(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[124]; _x1 ^= _workingKey[125]; _x2 ^= _workingKey[126]; _x3 ^= _workingKey[127]; - InverseLT(); Ib6(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[120]; _x1 ^= _workingKey[121]; _x2 ^= _workingKey[122]; _x3 ^= _workingKey[123]; - InverseLT(); Ib5(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[116]; _x1 ^= _workingKey[117]; _x2 ^= _workingKey[118]; _x3 ^= _workingKey[119]; - InverseLT(); Ib4(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[112]; _x1 ^= _workingKey[113]; _x2 ^= _workingKey[114]; _x3 ^= _workingKey[115]; - InverseLT(); Ib3(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[108]; _x1 ^= _workingKey[109]; _x2 ^= _workingKey[110]; _x3 ^= _workingKey[111]; - InverseLT(); Ib2(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[104]; _x1 ^= _workingKey[105]; _x2 ^= _workingKey[106]; _x3 ^= _workingKey[107]; - InverseLT(); Ib1(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[100]; _x1 ^= _workingKey[101]; _x2 ^= _workingKey[102]; _x3 ^= _workingKey[103]; - InverseLT(); Ib0(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[96]; _x1 ^= _workingKey[97]; _x2 ^= _workingKey[98]; _x3 ^= _workingKey[99]; - InverseLT(); Ib7(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[92]; _x1 ^= _workingKey[93]; _x2 ^= _workingKey[94]; _x3 ^= _workingKey[95]; - InverseLT(); Ib6(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[88]; _x1 ^= _workingKey[89]; _x2 ^= _workingKey[90]; _x3 ^= _workingKey[91]; - InverseLT(); Ib5(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[84]; _x1 ^= _workingKey[85]; _x2 ^= _workingKey[86]; _x3 ^= _workingKey[87]; - InverseLT(); Ib4(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[80]; _x1 ^= _workingKey[81]; _x2 ^= _workingKey[82]; _x3 ^= _workingKey[83]; - InverseLT(); Ib3(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[76]; _x1 ^= _workingKey[77]; _x2 ^= _workingKey[78]; _x3 ^= _workingKey[79]; - InverseLT(); Ib2(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[72]; _x1 ^= _workingKey[73]; _x2 ^= _workingKey[74]; _x3 ^= _workingKey[75]; - InverseLT(); Ib1(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[68]; _x1 ^= _workingKey[69]; _x2 ^= _workingKey[70]; _x3 ^= _workingKey[71]; - InverseLT(); Ib0(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[64]; _x1 ^= _workingKey[65]; _x2 ^= _workingKey[66]; _x3 ^= _workingKey[67]; - InverseLT(); Ib7(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[60]; _x1 ^= _workingKey[61]; _x2 ^= _workingKey[62]; _x3 ^= _workingKey[63]; - InverseLT(); Ib6(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[56]; _x1 ^= _workingKey[57]; _x2 ^= _workingKey[58]; _x3 ^= _workingKey[59]; - InverseLT(); Ib5(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[52]; _x1 ^= _workingKey[53]; _x2 ^= _workingKey[54]; _x3 ^= _workingKey[55]; - InverseLT(); Ib4(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[48]; _x1 ^= _workingKey[49]; _x2 ^= _workingKey[50]; _x3 ^= _workingKey[51]; - InverseLT(); Ib3(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[44]; _x1 ^= _workingKey[45]; _x2 ^= _workingKey[46]; _x3 ^= _workingKey[47]; - InverseLT(); Ib2(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[40]; _x1 ^= _workingKey[41]; _x2 ^= _workingKey[42]; _x3 ^= _workingKey[43]; - InverseLT(); Ib1(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[36]; _x1 ^= _workingKey[37]; _x2 ^= _workingKey[38]; _x3 ^= _workingKey[39]; - InverseLT(); Ib0(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[32]; _x1 ^= _workingKey[33]; _x2 ^= _workingKey[34]; _x3 ^= _workingKey[35]; - InverseLT(); Ib7(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[28]; _x1 ^= _workingKey[29]; _x2 ^= _workingKey[30]; _x3 ^= _workingKey[31]; - InverseLT(); Ib6(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[24]; _x1 ^= _workingKey[25]; _x2 ^= _workingKey[26]; _x3 ^= _workingKey[27]; - InverseLT(); Ib5(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[20]; _x1 ^= _workingKey[21]; _x2 ^= _workingKey[22]; _x3 ^= _workingKey[23]; - InverseLT(); Ib4(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[16]; _x1 ^= _workingKey[17]; _x2 ^= _workingKey[18]; _x3 ^= _workingKey[19]; - InverseLT(); Ib3(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[12]; _x1 ^= _workingKey[13]; _x2 ^= _workingKey[14]; _x3 ^= _workingKey[15]; - InverseLT(); Ib2(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[8]; _x1 ^= _workingKey[9]; _x2 ^= _workingKey[10]; _x3 ^= _workingKey[11]; - InverseLT(); Ib1(_x0, _x1, _x2, _x3); - _x0 ^= _workingKey[4]; _x1 ^= _workingKey[5]; _x2 ^= _workingKey[6]; _x3 ^= _workingKey[7]; - InverseLT(); Ib0(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[124]; + _x1 ^= _workingKey[125]; + _x2 ^= _workingKey[126]; + _x3 ^= _workingKey[127]; + + InverseLT(); + Ib6(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[120]; + _x1 ^= _workingKey[121]; + _x2 ^= _workingKey[122]; + _x3 ^= _workingKey[123]; + + InverseLT(); + Ib5(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[116]; + _x1 ^= _workingKey[117]; + _x2 ^= _workingKey[118]; + _x3 ^= _workingKey[119]; + + InverseLT(); + Ib4(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[112]; + _x1 ^= _workingKey[113]; + _x2 ^= _workingKey[114]; + _x3 ^= _workingKey[115]; + InverseLT(); + Ib3(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[108]; + _x1 ^= _workingKey[109]; + _x2 ^= _workingKey[110]; + _x3 ^= _workingKey[111]; + + InverseLT(); + Ib2(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[104]; + _x1 ^= _workingKey[105]; + _x2 ^= _workingKey[106]; + _x3 ^= _workingKey[107]; + + InverseLT(); + Ib1(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[100]; + _x1 ^= _workingKey[101]; + _x2 ^= _workingKey[102]; + _x3 ^= _workingKey[103]; + + InverseLT(); + Ib0(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[96]; + _x1 ^= _workingKey[97]; + _x2 ^= _workingKey[98]; + _x3 ^= _workingKey[99]; + + InverseLT(); + Ib7(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[92]; + _x1 ^= _workingKey[93]; + _x2 ^= _workingKey[94]; + _x3 ^= _workingKey[95]; + + InverseLT(); + Ib6(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[88]; + _x1 ^= _workingKey[89]; + _x2 ^= _workingKey[90]; + _x3 ^= _workingKey[91]; + + InverseLT(); + Ib5(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[84]; + _x1 ^= _workingKey[85]; + _x2 ^= _workingKey[86]; + _x3 ^= _workingKey[87]; + + InverseLT(); + Ib4(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[80]; + _x1 ^= _workingKey[81]; + _x2 ^= _workingKey[82]; + _x3 ^= _workingKey[83]; + + InverseLT(); + Ib3(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[76]; + _x1 ^= _workingKey[77]; + _x2 ^= _workingKey[78]; + _x3 ^= _workingKey[79]; + + InverseLT(); + Ib2(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[72]; + _x1 ^= _workingKey[73]; + _x2 ^= _workingKey[74]; + _x3 ^= _workingKey[75]; + + InverseLT(); + Ib1(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[68]; + _x1 ^= _workingKey[69]; + _x2 ^= _workingKey[70]; + _x3 ^= _workingKey[71]; + + InverseLT(); + Ib0(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[64]; + _x1 ^= _workingKey[65]; + _x2 ^= _workingKey[66]; + _x3 ^= _workingKey[67]; + + InverseLT(); + Ib7(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[60]; + _x1 ^= _workingKey[61]; + _x2 ^= _workingKey[62]; + _x3 ^= _workingKey[63]; + + InverseLT(); + Ib6(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[56]; + _x1 ^= _workingKey[57]; + _x2 ^= _workingKey[58]; + _x3 ^= _workingKey[59]; + + InverseLT(); + Ib5(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[52]; + _x1 ^= _workingKey[53]; + _x2 ^= _workingKey[54]; + _x3 ^= _workingKey[55]; + + InverseLT(); + Ib4(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[48]; + _x1 ^= _workingKey[49]; + _x2 ^= _workingKey[50]; + _x3 ^= _workingKey[51]; + + InverseLT(); + Ib3(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[44]; + _x1 ^= _workingKey[45]; + _x2 ^= _workingKey[46]; + _x3 ^= _workingKey[47]; + + InverseLT(); + Ib2(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[40]; + _x1 ^= _workingKey[41]; + _x2 ^= _workingKey[42]; + _x3 ^= _workingKey[43]; + + InverseLT(); + Ib1(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[36]; + _x1 ^= _workingKey[37]; + _x2 ^= _workingKey[38]; + _x3 ^= _workingKey[39]; + + InverseLT(); + Ib0(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[32]; + _x1 ^= _workingKey[33]; + _x2 ^= _workingKey[34]; + _x3 ^= _workingKey[35]; + + InverseLT(); + Ib7(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[28]; + _x1 ^= _workingKey[29]; + _x2 ^= _workingKey[30]; + _x3 ^= _workingKey[31]; + + InverseLT(); + Ib6(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[24]; + _x1 ^= _workingKey[25]; + _x2 ^= _workingKey[26]; + _x3 ^= _workingKey[27]; + + InverseLT(); + Ib5(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[20]; + _x1 ^= _workingKey[21]; + _x2 ^= _workingKey[22]; + _x3 ^= _workingKey[23]; + + InverseLT(); + Ib4(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[16]; + _x1 ^= _workingKey[17]; + _x2 ^= _workingKey[18]; + _x3 ^= _workingKey[19]; + + InverseLT(); + Ib3(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[12]; + _x1 ^= _workingKey[13]; + _x2 ^= _workingKey[14]; + _x3 ^= _workingKey[15]; + + InverseLT(); + Ib2(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[8]; + _x1 ^= _workingKey[9]; + _x2 ^= _workingKey[10]; + _x3 ^= _workingKey[11]; + + InverseLT(); + Ib1(_x0, _x1, _x2, _x3); + + _x0 ^= _workingKey[4]; + _x1 ^= _workingKey[5]; + _x2 ^= _workingKey[6]; + _x3 ^= _workingKey[7]; + + InverseLT(); + Ib0(_x0, _x1, _x2, _x3); WordToBytes(_x3 ^ _workingKey[3], outputBuffer, outputOffset); WordToBytes(_x2 ^ _workingKey[2], outputBuffer, outputOffset + 4); @@ -187,7 +414,6 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC return BlockSize; } - /// /// Expand a user-supplied key material into a session key. /// @@ -198,9 +424,7 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC /// is not multiple of 4 bytes. private int[] MakeWorkingKey(byte[] key) { - // // pad key to 256 bits - // var kPad = new int[16]; int off; var length = 0; @@ -223,15 +447,11 @@ private int[] MakeWorkingKey(byte[] key) throw new ArgumentException("key must be a multiple of 4 bytes"); } - // // expand the padded key up to 33 x 128 bits of key material - // const int amount = (Rounds + 1) * 4; var w = new int[amount]; - // // compute w0 to w7 from w-8 to w-1 - // for (var i = 8; i < 16; i++) { kPad[i] = RotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ Phi ^ (i - 8), 11); @@ -239,134 +459,263 @@ private int[] MakeWorkingKey(byte[] key) Buffer.BlockCopy(kPad, 8, w, 0, 8); - // // compute w8 to w136 - // for (var i = 8; i < amount; i++) { w[i] = RotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ Phi ^ i, 11); } - // // create the working keys by processing w with the Sbox and IP - // Sb3(w[0], w[1], w[2], w[3]); - w[0] = _x0; w[1] = _x1; w[2] = _x2; w[3] = _x3; + w[0] = _x0; + w[1] = _x1; + w[2] = _x2; + w[3] = _x3; + Sb2(w[4], w[5], w[6], w[7]); - w[4] = _x0; w[5] = _x1; w[6] = _x2; w[7] = _x3; + w[4] = _x0; + w[5] = _x1; + w[6] = _x2; + w[7] = _x3; + Sb1(w[8], w[9], w[10], w[11]); - w[8] = _x0; w[9] = _x1; w[10] = _x2; w[11] = _x3; + w[8] = _x0; + w[9] = _x1; + w[10] = _x2; + w[11] = _x3; + Sb0(w[12], w[13], w[14], w[15]); - w[12] = _x0; w[13] = _x1; w[14] = _x2; w[15] = _x3; + w[12] = _x0; + w[13] = _x1; + w[14] = _x2; + w[15] = _x3; + Sb7(w[16], w[17], w[18], w[19]); - w[16] = _x0; w[17] = _x1; w[18] = _x2; w[19] = _x3; + w[16] = _x0; + w[17] = _x1; + w[18] = _x2; + w[19] = _x3; + Sb6(w[20], w[21], w[22], w[23]); - w[20] = _x0; w[21] = _x1; w[22] = _x2; w[23] = _x3; + w[20] = _x0; + w[21] = _x1; + w[22] = _x2; + w[23] = _x3; + Sb5(w[24], w[25], w[26], w[27]); - w[24] = _x0; w[25] = _x1; w[26] = _x2; w[27] = _x3; + w[24] = _x0; + w[25] = _x1; + w[26] = _x2; + w[27] = _x3; + Sb4(w[28], w[29], w[30], w[31]); - w[28] = _x0; w[29] = _x1; w[30] = _x2; w[31] = _x3; + w[28] = _x0; + w[29] = _x1; + w[30] = _x2; + w[31] = _x3; + Sb3(w[32], w[33], w[34], w[35]); - w[32] = _x0; w[33] = _x1; w[34] = _x2; w[35] = _x3; + w[32] = _x0; + w[33] = _x1; + w[34] = _x2; + w[35] = _x3; + Sb2(w[36], w[37], w[38], w[39]); - w[36] = _x0; w[37] = _x1; w[38] = _x2; w[39] = _x3; + w[36] = _x0; + w[37] = _x1; + w[38] = _x2; + w[39] = _x3; + Sb1(w[40], w[41], w[42], w[43]); - w[40] = _x0; w[41] = _x1; w[42] = _x2; w[43] = _x3; + w[40] = _x0; + w[41] = _x1; + w[42] = _x2; + w[43] = _x3; + Sb0(w[44], w[45], w[46], w[47]); - w[44] = _x0; w[45] = _x1; w[46] = _x2; w[47] = _x3; + w[44] = _x0; + w[45] = _x1; + w[46] = _x2; + w[47] = _x3; + Sb7(w[48], w[49], w[50], w[51]); - w[48] = _x0; w[49] = _x1; w[50] = _x2; w[51] = _x3; + w[48] = _x0; + w[49] = _x1; + w[50] = _x2; + w[51] = _x3; + Sb6(w[52], w[53], w[54], w[55]); - w[52] = _x0; w[53] = _x1; w[54] = _x2; w[55] = _x3; + w[52] = _x0; + w[53] = _x1; + w[54] = _x2; + w[55] = _x3; + Sb5(w[56], w[57], w[58], w[59]); - w[56] = _x0; w[57] = _x1; w[58] = _x2; w[59] = _x3; + w[56] = _x0; + w[57] = _x1; + w[58] = _x2; + w[59] = _x3; + Sb4(w[60], w[61], w[62], w[63]); - w[60] = _x0; w[61] = _x1; w[62] = _x2; w[63] = _x3; + w[60] = _x0; + w[61] = _x1; + w[62] = _x2; + w[63] = _x3; + Sb3(w[64], w[65], w[66], w[67]); - w[64] = _x0; w[65] = _x1; w[66] = _x2; w[67] = _x3; + w[64] = _x0; + w[65] = _x1; + w[66] = _x2; + w[67] = _x3; + Sb2(w[68], w[69], w[70], w[71]); - w[68] = _x0; w[69] = _x1; w[70] = _x2; w[71] = _x3; + w[68] = _x0; + w[69] = _x1; + w[70] = _x2; + w[71] = _x3; + Sb1(w[72], w[73], w[74], w[75]); - w[72] = _x0; w[73] = _x1; w[74] = _x2; w[75] = _x3; + w[72] = _x0; + w[73] = _x1; + w[74] = _x2; + w[75] = _x3; + Sb0(w[76], w[77], w[78], w[79]); - w[76] = _x0; w[77] = _x1; w[78] = _x2; w[79] = _x3; + w[76] = _x0; + w[77] = _x1; + w[78] = _x2; + w[79] = _x3; + Sb7(w[80], w[81], w[82], w[83]); - w[80] = _x0; w[81] = _x1; w[82] = _x2; w[83] = _x3; + w[80] = _x0; + w[81] = _x1; + w[82] = _x2; + w[83] = _x3; + Sb6(w[84], w[85], w[86], w[87]); - w[84] = _x0; w[85] = _x1; w[86] = _x2; w[87] = _x3; + w[84] = _x0; + w[85] = _x1; + w[86] = _x2; + w[87] = _x3; + Sb5(w[88], w[89], w[90], w[91]); - w[88] = _x0; w[89] = _x1; w[90] = _x2; w[91] = _x3; + w[88] = _x0; + w[89] = _x1; + w[90] = _x2; + w[91] = _x3; + Sb4(w[92], w[93], w[94], w[95]); - w[92] = _x0; w[93] = _x1; w[94] = _x2; w[95] = _x3; + w[92] = _x0; + w[93] = _x1; + w[94] = _x2; + w[95] = _x3; + Sb3(w[96], w[97], w[98], w[99]); - w[96] = _x0; w[97] = _x1; w[98] = _x2; w[99] = _x3; + w[96] = _x0; + w[97] = _x1; + w[98] = _x2; + w[99] = _x3; + Sb2(w[100], w[101], w[102], w[103]); - w[100] = _x0; w[101] = _x1; w[102] = _x2; w[103] = _x3; + w[100] = _x0; + w[101] = _x1; + w[102] = _x2; + w[103] = _x3; + Sb1(w[104], w[105], w[106], w[107]); - w[104] = _x0; w[105] = _x1; w[106] = _x2; w[107] = _x3; + w[104] = _x0; + w[105] = _x1; + w[106] = _x2; + w[107] = _x3; + Sb0(w[108], w[109], w[110], w[111]); - w[108] = _x0; w[109] = _x1; w[110] = _x2; w[111] = _x3; + w[108] = _x0; + w[109] = _x1; + w[110] = _x2; + w[111] = _x3; + Sb7(w[112], w[113], w[114], w[115]); - w[112] = _x0; w[113] = _x1; w[114] = _x2; w[115] = _x3; + w[112] = _x0; + w[113] = _x1; + w[114] = _x2; + w[115] = _x3; + Sb6(w[116], w[117], w[118], w[119]); - w[116] = _x0; w[117] = _x1; w[118] = _x2; w[119] = _x3; + w[116] = _x0; + w[117] = _x1; + w[118] = _x2; + w[119] = _x3; + Sb5(w[120], w[121], w[122], w[123]); - w[120] = _x0; w[121] = _x1; w[122] = _x2; w[123] = _x3; + w[120] = _x0; + w[121] = _x1; + w[122] = _x2; + w[123] = _x3; + Sb4(w[124], w[125], w[126], w[127]); - w[124] = _x0; w[125] = _x1; w[126] = _x2; w[127] = _x3; + w[124] = _x0; + w[125] = _x1; + w[126] = _x2; + w[127] = _x3; + Sb3(w[128], w[129], w[130], w[131]); - w[128] = _x0; w[129] = _x1; w[130] = _x2; w[131] = _x3; + w[128] = _x0; + w[129] = _x1; + w[130] = _x2; + w[131] = _x3; return w; } private static int RotateLeft(int x, int bits) { - return ((x << bits) | (int)((uint)x >> (32 - bits))); + return (x << bits) | (int) ((uint) x >> (32 - bits)); } private static int RotateRight(int x, int bits) { - return ((int)((uint)x >> bits) | (x << (32 - bits))); + return (int) ((uint) x >> bits) | (x << (32 - bits)); } private static int BytesToWord(byte[] src, int srcOff) { - return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) | - ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff))); + return ((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) | + ((src[srcOff + 2] & 0xff) << 8) | (src[srcOff + 3] & 0xff); } private static void WordToBytes(int word, byte[] dst, int dstOff) { - dst[dstOff + 3] = (byte)(word); - dst[dstOff + 2] = (byte)((uint)word >> 8); - dst[dstOff + 1] = (byte)((uint)word >> 16); - dst[dstOff] = (byte)((uint)word >> 24); + dst[dstOff + 3] = (byte) word; + dst[dstOff + 2] = (byte) ((uint)word >> 8); + dst[dstOff + 1] = (byte) ((uint)word >> 16); + dst[dstOff] = (byte) ((uint)word >> 24); } /* - * The sboxes below are based on the work of Brian Gladman and - * Sam Simpson, whose original notice appears below. - *

- * For further details see: - * http://fp.gladman.plus.com/cryptography_technology/serpent/ - *

- */ - - /* Partially optimised Serpent S Box bool functions derived */ - /* using a recursive descent analyser but without a full search */ - /* of all subtrees. This set of S boxes is the result of work */ - /* by Sam Simpson and Brian Gladman using the spare time on a */ - /* cluster of high capacity servers to search for S boxes with */ - /* this customised search engine. There are now an average of */ - /* 15.375 terms per S box. */ - /* */ - /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */ - /* and Sam Simpson (s.simpson@mia.co.uk) */ - /* 17th December 1998 */ - /* */ - /* We hereby give permission for information in this file to be */ - /* used freely subject only to acknowledgement of its origin. */ + * The sboxes below are based on the work of Brian Gladman and + * Sam Simpson, whose original notice appears below. + * + * For further details see: + * http://fp.gladman.plus.com/cryptography_technology/serpent/ + * + */ + + /* + * Partially optimised Serpent S Box bool functions derived + * using a recursive descent analyser but without a full search + * of all subtrees. This set of S boxes is the result of work + * by Sam Simpson and Brian Gladman using the spare time on a + * cluster of high capacity servers to search for S boxes with + * this customised search engine. There are now an average of + * 15.375 terms per S box. + * + * Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) + * and Sam Simpson (s.simpson@mia.co.uk) + * 17th December 1998 + * + * We hereby give permission for information in this file to be + * used freely subject only to acknowledgement of its origin. + */ /// /// S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms. @@ -377,13 +726,13 @@ private static void WordToBytes(int word, byte[] dst, int dstOff) /// The d. private void Sb0(int a, int b, int c, int d) { - int t1 = a ^ d; - int t3 = c ^ t1; - int t4 = b ^ t3; + var t1 = a ^ d; + var t3 = c ^ t1; + var t4 = b ^ t3; _x3 = (a & d) ^ t4; - int t7 = a ^ (b & t1); + var t7 = a ^ (b & t1); _x2 = t4 ^ (c | t7); - int t12 = _x3 & (t3 ^ t7); + var t12 = _x3 & (t3 ^ t7); _x1 = (~t3) ^ t12; _x0 = t12 ^ (~t7); } @@ -397,12 +746,12 @@ private void Sb0(int a, int b, int c, int d) /// The d. private void Ib0(int a, int b, int c, int d) { - int t1 = ~a; - int t2 = a ^ b; - int t4 = d ^ (t1 | t2); - int t5 = c ^ t4; + var t1 = ~a; + var t2 = a ^ b; + var t4 = d ^ (t1 | t2); + var t5 = c ^ t4; _x2 = t2 ^ t5; - int t8 = t1 ^ (d & t2); + var t8 = t1 ^ (d & t2); _x1 = t4 ^ (_x2 & t8); _x3 = (a & t4) ^ (t5 | _x1); _x0 = _x3 ^ (t5 ^ t8); @@ -417,13 +766,13 @@ private void Ib0(int a, int b, int c, int d) /// The d. private void Sb1(int a, int b, int c, int d) { - int t2 = b ^ (~a); - int t5 = c ^ (a | t2); + var t2 = b ^ (~a); + var t5 = c ^ (a | t2); _x2 = d ^ t5; - int t7 = b ^ (d | t2); - int t8 = t2 ^ _x2; + var t7 = b ^ (d | t2); + var t8 = t2 ^ _x2; _x3 = t8 ^ (t5 & t7); - int t11 = t5 ^ t7; + var t11 = t5 ^ t7; _x1 = _x3 ^ t11; _x0 = t5 ^ (t8 & t11); } @@ -437,15 +786,15 @@ private void Sb1(int a, int b, int c, int d) /// The d. private void Ib1(int a, int b, int c, int d) { - int t1 = b ^ d; - int t3 = a ^ (b & t1); - int t4 = t1 ^ t3; + var t1 = b ^ d; + var t3 = a ^ (b & t1); + var t4 = t1 ^ t3; _x3 = c ^ t4; - int t7 = b ^ (t1 & t3); - int t8 = _x3 | t7; + var t7 = b ^ (t1 & t3); + var t8 = _x3 | t7; _x1 = t3 ^ t8; - int t10 = ~_x1; - int t11 = _x3 ^ t7; + var t10 = ~_x1; + var t11 = _x3 ^ t7; _x0 = t10 ^ t11; _x2 = t4 ^ (t10 | t11); } @@ -459,13 +808,13 @@ private void Ib1(int a, int b, int c, int d) /// The d. private void Sb2(int a, int b, int c, int d) { - int t1 = ~a; - int t2 = b ^ d; - int t3 = c & t1; + var t1 = ~a; + var t2 = b ^ d; + var t3 = c & t1; _x0 = t2 ^ t3; - int t5 = c ^ t1; - int t6 = c ^ _x0; - int t7 = b & t6; + var t5 = c ^ t1; + var t6 = c ^ _x0; + var t7 = b & t6; _x3 = t5 ^ t7; _x2 = a ^ ((d | t7) & (_x0 | t5)); _x1 = (t2 ^ _x3) ^ (_x2 ^ (d | t1)); @@ -480,18 +829,18 @@ private void Sb2(int a, int b, int c, int d) /// The d. private void Ib2(int a, int b, int c, int d) { - int t1 = b ^ d; - int t2 = ~t1; - int t3 = a ^ c; - int t4 = c ^ t1; - int t5 = b & t4; + var t1 = b ^ d; + var t2 = ~t1; + var t3 = a ^ c; + var t4 = c ^ t1; + var t5 = b & t4; _x0 = t3 ^ t5; - int t7 = a | t2; - int t8 = d ^ t7; - int t9 = t3 | t8; + var t7 = a | t2; + var t8 = d ^ t7; + var t9 = t3 | t8; _x3 = t1 ^ t9; - int t11 = ~t4; - int t12 = _x0 | _x3; + var t11 = ~t4; + var t12 = _x0 | _x3; _x1 = t11 ^ t12; _x2 = (d & t11) ^ (t3 ^ t12); } @@ -505,18 +854,18 @@ private void Ib2(int a, int b, int c, int d) /// The d. private void Sb3(int a, int b, int c, int d) { - int t1 = a ^ b; - int t2 = a & c; - int t3 = a | d; - int t4 = c ^ d; - int t5 = t1 & t3; - int t6 = t2 | t5; + var t1 = a ^ b; + var t2 = a & c; + var t3 = a | d; + var t4 = c ^ d; + var t5 = t1 & t3; + var t6 = t2 | t5; _x2 = t4 ^ t6; - int t8 = b ^ t3; - int t9 = t6 ^ t8; - int t10 = t4 & t9; + var t8 = b ^ t3; + var t9 = t6 ^ t8; + var t10 = t4 & t9; _x0 = t1 ^ t10; - int t12 = _x2 & _x0; + var t12 = _x2 & _x0; _x1 = t9 ^ t12; _x3 = (b | d) ^ (t4 ^ t12); } @@ -530,18 +879,18 @@ private void Sb3(int a, int b, int c, int d) /// The d. private void Ib3(int a, int b, int c, int d) { - int t1 = a | b; - int t2 = b ^ c; - int t3 = b & t2; - int t4 = a ^ t3; - int t5 = c ^ t4; - int t6 = d | t4; + var t1 = a | b; + var t2 = b ^ c; + var t3 = b & t2; + var t4 = a ^ t3; + var t5 = c ^ t4; + var t6 = d | t4; _x0 = t2 ^ t6; - int t8 = t2 | t6; - int t9 = d ^ t8; + var t8 = t2 | t6; + var t9 = d ^ t8; _x2 = t5 ^ t9; - int t11 = t1 ^ t9; - int t12 = _x0 & t11; + var t11 = t1 ^ t9; + var t12 = _x0 & t11; _x3 = t4 ^ t12; _x1 = _x3 ^ (_x0 ^ t11); } @@ -555,17 +904,17 @@ private void Ib3(int a, int b, int c, int d) /// The d. private void Sb4(int a, int b, int c, int d) { - int t1 = a ^ d; - int t2 = d & t1; - int t3 = c ^ t2; - int t4 = b | t3; + var t1 = a ^ d; + var t2 = d & t1; + var t3 = c ^ t2; + var t4 = b | t3; _x3 = t1 ^ t4; - int t6 = ~b; - int t7 = t1 | t6; + var t6 = ~b; + var t7 = t1 | t6; _x0 = t3 ^ t7; - int t9 = a & _x0; - int t10 = t1 ^ t6; - int t11 = t4 & t10; + var t9 = a & _x0; + var t10 = t1 ^ t6; + var t11 = t4 & t10; _x2 = t9 ^ t11; _x1 = (a ^ t3) ^ (t10 & _x2); } @@ -579,17 +928,17 @@ private void Sb4(int a, int b, int c, int d) /// The d. private void Ib4(int a, int b, int c, int d) { - int t1 = c | d; - int t2 = a & t1; - int t3 = b ^ t2; - int t4 = a & t3; - int t5 = c ^ t4; + var t1 = c | d; + var t2 = a & t1; + var t3 = b ^ t2; + var t4 = a & t3; + var t5 = c ^ t4; _x1 = d ^ t5; - int t7 = ~a; - int t8 = t5 & _x1; + var t7 = ~a; + var t8 = t5 & _x1; _x3 = t3 ^ t8; - int t10 = _x1 | t7; - int t11 = d ^ t10; + var t10 = _x1 | t7; + var t11 = d ^ t10; _x0 = _x3 ^ t11; _x2 = (t3 & t11) ^ (_x1 ^ t7); } @@ -603,18 +952,18 @@ private void Ib4(int a, int b, int c, int d) /// The d. private void Sb5(int a, int b, int c, int d) { - int t1 = ~a; - int t2 = a ^ b; - int t3 = a ^ d; - int t4 = c ^ t1; - int t5 = t2 | t3; + var t1 = ~a; + var t2 = a ^ b; + var t3 = a ^ d; + var t4 = c ^ t1; + var t5 = t2 | t3; _x0 = t4 ^ t5; - int t7 = d & _x0; - int t8 = t2 ^ _x0; + var t7 = d & _x0; + var t8 = t2 ^ _x0; _x1 = t7 ^ t8; - int t10 = t1 | _x0; - int t11 = t2 | t7; - int t12 = t3 ^ t10; + var t10 = t1 | _x0; + var t11 = t2 | t7; + var t12 = t3 ^ t10; _x2 = t11 ^ t12; _x3 = (b ^ t7) ^ (_x1 & t12); } @@ -628,17 +977,17 @@ private void Sb5(int a, int b, int c, int d) /// The d. private void Ib5(int a, int b, int c, int d) { - int t1 = ~c; - int t2 = b & t1; - int t3 = d ^ t2; - int t4 = a & t3; - int t5 = b ^ t1; + var t1 = ~c; + var t2 = b & t1; + var t3 = d ^ t2; + var t4 = a & t3; + var t5 = b ^ t1; _x3 = t4 ^ t5; - int t7 = b | _x3; - int t8 = a & t7; + var t7 = b | _x3; + var t8 = a & t7; _x1 = t3 ^ t8; - int t10 = a | d; - int t11 = t1 ^ t7; + var t10 = a | d; + var t11 = t1 ^ t7; _x0 = t10 ^ t11; _x2 = (b & t10) ^ (t4 | (a ^ c)); } @@ -652,17 +1001,17 @@ private void Ib5(int a, int b, int c, int d) /// The d. private void Sb6(int a, int b, int c, int d) { - int t1 = ~a; - int t2 = a ^ d; - int t3 = b ^ t2; - int t4 = t1 | t2; - int t5 = c ^ t4; + var t1 = ~a; + var t2 = a ^ d; + var t3 = b ^ t2; + var t4 = t1 | t2; + var t5 = c ^ t4; _x1 = b ^ t5; - int t7 = t2 | _x1; - int t8 = d ^ t7; - int t9 = t5 & t8; + var t7 = t2 | _x1; + var t8 = d ^ t7; + var t9 = t5 & t8; _x2 = t3 ^ t9; - int t11 = t5 ^ t8; + var t11 = t5 ^ t8; _x0 = _x2 ^ t11; _x3 = (~t5) ^ (t3 & t11); } @@ -676,17 +1025,17 @@ private void Sb6(int a, int b, int c, int d) /// The d. private void Ib6(int a, int b, int c, int d) { - int t1 = ~a; - int t2 = a ^ b; - int t3 = c ^ t2; - int t4 = c | t1; - int t5 = d ^ t4; + var t1 = ~a; + var t2 = a ^ b; + var t3 = c ^ t2; + var t4 = c | t1; + var t5 = d ^ t4; _x1 = t3 ^ t5; - int t7 = t3 & t5; - int t8 = t2 ^ t7; - int t9 = b | t8; + var t7 = t3 & t5; + var t8 = t2 ^ t7; + var t9 = b | t8; _x3 = t5 ^ t9; - int t11 = b | _x3; + var t11 = b | _x3; _x0 = t8 ^ t11; _x2 = (d & t1) ^ (t3 ^ t11); } @@ -700,18 +1049,18 @@ private void Ib6(int a, int b, int c, int d) /// The d. private void Sb7(int a, int b, int c, int d) { - int t1 = b ^ c; - int t2 = c & t1; - int t3 = d ^ t2; - int t4 = a ^ t3; - int t5 = d | t1; - int t6 = t4 & t5; + var t1 = b ^ c; + var t2 = c & t1; + var t3 = d ^ t2; + var t4 = a ^ t3; + var t5 = d | t1; + var t6 = t4 & t5; _x1 = b ^ t6; - int t8 = t3 | _x1; - int t9 = a & t4; + var t8 = t3 | _x1; + var t9 = a & t4; _x3 = t1 ^ t9; - int t11 = t4 ^ t8; - int t12 = _x3 & t11; + var t11 = t4 ^ t8; + var t12 = _x3 & t11; _x2 = t3 ^ t12; _x0 = (~t11) ^ (_x3 & _x2); } @@ -725,12 +1074,12 @@ private void Sb7(int a, int b, int c, int d) /// The d. private void Ib7(int a, int b, int c, int d) { - int t3 = c | (a & b); - int t4 = d & (a | b); + var t3 = c | (a & b); + var t4 = d & (a | b); _x3 = t3 ^ t4; - int t6 = ~d; - int t7 = b ^ t4; - int t9 = t7 | (_x3 ^ t6); + var t6 = ~d; + var t7 = b ^ t4; + var t9 = t7 | (_x3 ^ t6); _x1 = a ^ t9; _x0 = (c ^ t7) ^ (d | _x1); _x2 = (t3 ^ _x1) ^ (_x0 ^ (a & _x3)); @@ -741,10 +1090,10 @@ private void Ib7(int a, int b, int c, int d) /// private void LT() { - int x0 = RotateLeft(_x0, 13); - int x2 = RotateLeft(_x2, 3); - int x1 = _x1 ^ x0 ^ x2; - int x3 = _x3 ^ x2 ^ x0 << 3; + var x0 = RotateLeft(_x0, 13); + var x2 = RotateLeft(_x2, 3); + var x1 = _x1 ^ x0 ^ x2; + var x3 = _x3 ^ x2 ^ x0 << 3; _x1 = RotateLeft(x1, 1); _x3 = RotateLeft(x3, 7); @@ -757,10 +1106,10 @@ private void LT() ///
private void InverseLT() { - int x2 = RotateRight(_x2, 22) ^ _x3 ^ (_x1 << 7); - int x0 = RotateRight(_x0, 5) ^ _x1 ^ _x3; - int x3 = RotateRight(_x3, 7); - int x1 = RotateRight(_x1, 1); + var x2 = RotateRight(_x2, 22) ^ _x3 ^ (_x1 << 7); + var x0 = RotateRight(_x0, 5) ^ _x1 ^ _x3; + var x3 = RotateRight(_x3, 7); + var x1 = RotateRight(_x1, 1); _x3 = x3 ^ x2 ^ x0 << 3; _x1 = x1 ^ x0 ^ x2; _x2 = RotateRight(x2, 3); diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs index a9db5db53..f83ed24d0 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs @@ -70,7 +70,7 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC } } - byte[] temp = new byte[BlockSize]; + var temp = new byte[BlockSize]; DesFunc(_encryptionKey1, inputBuffer, inputOffset, temp, 0); DesFunc(_encryptionKey2, temp, 0, temp, 0); @@ -93,10 +93,14 @@ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputC public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { if ((inputOffset + BlockSize) > inputBuffer.Length) + { throw new IndexOutOfRangeException("input buffer too short"); + } if ((outputOffset + BlockSize) > outputBuffer.Length) + { throw new IndexOutOfRangeException("output buffer too short"); + } if (_decryptionKey1 == null || _decryptionKey2 == null || _decryptionKey3 == null) { @@ -122,7 +126,7 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC } } - byte[] temp = new byte[BlockSize]; + var temp = new byte[BlockSize]; DesFunc(_decryptionKey3, inputBuffer, inputOffset, temp, 0); DesFunc(_decryptionKey2, temp, 0, temp, 0); @@ -138,8 +142,10 @@ protected override void ValidateKey() { var keySize = Key.Length * 8; - if (!(keySize == 128 || keySize == 128 + 64)) + if (keySize is not (128 or 128 + 64)) + { throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize)); + } } } } diff --git a/src/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs b/src/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs index 8f7c8bba0..ac33dce9c 100644 --- a/src/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers { /// - /// Implements Twofish cipher algorithm + /// Implements Twofish cipher algorithm. /// public sealed class TwofishCipher : BlockCipher { @@ -20,10 +20,10 @@ public TwofishCipher(byte[] key, CipherMode mode, CipherPadding padding) { var keySize = key.Length * 8; - if (!(keySize == 128 || keySize == 192 || keySize == 256)) + if (keySize is not (128 or 192 or 256)) + { throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize)); - - // TODO: Refactor this algorithm + } // calculate the MDS matrix var m1 = new int[2]; @@ -139,8 +139,6 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC return BlockSize; } - #region Static Definition Tables - private static readonly byte[] P = { // p0 @@ -160,6 +158,7 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0, + // p1 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, @@ -179,13 +178,11 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91 }; - #endregion - /** - * Define the fixed p0/p1 permutations used in keyed S-box lookup. - * By changing the following constant definitions, the S-boxes will - * automatically Get changed in the Twofish engine. - */ + * Define the fixed p0/p1 permutations used in keyed S-box lookup. + * By changing the following constant definitions, the S-boxes will + * automatically Get changed in the Twofish engine. + */ private const int P_00 = 1; private const int P_01 = 0; private const int P_02 = 0; @@ -217,10 +214,6 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC private const int RS_GF_FDBK = 0x14D; // field generator - //==================================== - // Useful constants - //==================================== - private const int ROUNDS = 16; private const int MAX_ROUNDS = 16; // bytes = 128 bits private const int MAX_KEY_BITS = 256; @@ -240,6 +233,8 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC private readonly int[] gMDS2 = new int[MAX_KEY_BITS]; private readonly int[] gMDS3 = new int[MAX_KEY_BITS]; + private readonly int _k64Cnt; + /** * gSubKeys[] and gSBox[] are eventually used in the * encryption and decryption methods. @@ -247,8 +242,6 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC private int[] gSubKeys; private int[] gSBox; - private readonly int _k64Cnt; - private void SetKey(byte[] key) { var k32e = new int[MAX_KEY_BITS / 64]; // 4 @@ -387,6 +380,7 @@ private int F32(int x, int[] k32) gMDS3[(P[P_31 * 256 + (P[P_32 * 256 + b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)]; break; } + return result; } @@ -402,6 +396,7 @@ private int F32(int x, int[] k32) private static int RS_MDS_Encode(int k0, int k1) { var r = k1; + // shift 1 byte at a time r = RS_rem(r); r = RS_rem(r); @@ -432,7 +427,7 @@ private static int RS_rem(int x) ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff; var g3 = ((int)((uint)b >> 1) ^ ((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2; - return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b); + return (x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b; } private static int LFSR1(int x) @@ -496,7 +491,7 @@ private static int Fe32_3(int[] gSBox1, int x) private static int BytesTo32Bits(byte[] b, int p) { - return ((b[p] & 0xff)) | + return (b[p] & 0xff) | ((b[p + 1] & 0xff) << 8) | ((b[p + 2] & 0xff) << 16) | ((b[p + 3] & 0xff) << 24); diff --git a/src/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs index 06275bdad..be84f7f83 100644 --- a/src/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs @@ -1,5 +1,6 @@ using System; using System.Security.Cryptography; + using Renci.SshNet.Abstractions; using Renci.SshNet.Common; @@ -10,9 +11,9 @@ namespace Renci.SshNet.Security.Cryptography ///
public class DsaDigitalSignature : DigitalSignature, IDisposable { - private HashAlgorithm _hash; - private readonly DsaKey _key; + private HashAlgorithm _hash; + private bool _isDisposed; /// /// Initializes a new instance of the class. @@ -22,7 +23,9 @@ public class DsaDigitalSignature : DigitalSignature, IDisposable public DsaDigitalSignature(DsaKey key) { if (key == null) - throw new ArgumentNullException("key"); + { + throw new ArgumentNullException(nameof(key)); + } _key = key; @@ -45,9 +48,11 @@ public override bool Verify(byte[] input, byte[] signature) var hm = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 })); if (signature.Length != 40) + { throw new InvalidOperationException("Invalid signature."); + } - // Extract r and s numbers from the signature + // Extract r and s numbers from the signature var rBytes = new byte[21]; var sBytes = new byte[21]; @@ -60,29 +65,33 @@ public override bool Verify(byte[] input, byte[] signature) var r = new BigInteger(rBytes); var s = new BigInteger(sBytes); - // Reject the signature if 0 < r < q or 0 < s < q is not satisfied. + // Reject the signature if 0 < r < q or 0 < s < q is not satisfied. if (r <= 0 || r >= _key.Q) + { return false; + } if (s <= 0 || s >= _key.Q) + { return false; + } - // Calculate w = s−1 mod q + // Calculate w = s−1 mod q var w = BigInteger.ModInverse(s, _key.Q); - // Calculate u1 = H(m)·w mod q + // Calculate u1 = H(m)·w mod q var u1 = hm * w % _key.Q; - // Calculate u2 = r * w mod q + // Calculate u2 = r * w mod q var u2 = r * w % _key.Q; u1 = BigInteger.ModPow(_key.G, u1, _key.P); u2 = BigInteger.ModPow(_key.Y, u2, _key.P); - // Calculate v = ((g pow u1 * y pow u2) mod p) mod q + // Calculate v = ((g pow u1 * y pow u2) mod p) mod q var v = ((u1 * u2) % _key.P) % _key.Q; - // The signature is valid if v = r + // The signature is valid if v = r return v == r; } @@ -105,37 +114,40 @@ public override byte[] Sign(byte[] input) do { - BigInteger k = BigInteger.Zero; + var k = BigInteger.Zero; do { - // Generate a random per-message value k where 0 < k < q + // Generate a random per-message value k where 0 < k < q var bitLength = _key.Q.BitLength; if (_key.Q < BigInteger.Zero) + { throw new SshException("Invalid DSA key."); + } while (k <= 0 || k >= _key.Q) { k = BigInteger.Random(bitLength); } - // Calculate r = ((g pow k) mod p) mod q + // Calculate r = ((g pow k) mod p) mod q r = BigInteger.ModPow(_key.G, k, _key.P) % _key.Q; - // In the unlikely case that r = 0, start again with a different random k - } while (r.IsZero); - + // In the unlikely case that r = 0, start again with a different random k + } + while (r.IsZero); - // Calculate s = ((k pow −1)(H(m) + x*r)) mod q - k = (BigInteger.ModInverse(k, _key.Q) * (m + _key.X * r)); + // Calculate s = ((k pow −1)(H(m) + x*r)) mod q + k = BigInteger.ModInverse(k, _key.Q) * (m + (_key.X * r)); s = k % _key.Q; - // In the unlikely case that s = 0, start again with a different random k - } while (s.IsZero); + // In the unlikely case that s = 0, start again with a different random k + } + while (s.IsZero); - // The signature is (r, s) + // The signature is (r, s) var signature = new byte[40]; // issue #1918: pad part with zero's on the left if length is less than 20 @@ -149,27 +161,25 @@ public override byte[] Sign(byte[] input) return signature; } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -185,14 +195,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~DsaDigitalSignature() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs index 5e9907f7b..bfb185a65 100644 --- a/src/Renci.SshNet/Security/Cryptography/DsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/DsaKey.cs @@ -5,10 +5,13 @@ namespace Renci.SshNet.Security { /// - /// Contains DSA private and public key + /// Contains DSA private and public key. /// public class DsaKey : Key, IDisposable { + private DsaDigitalSignature _digitalSignature; + private bool _isDisposed; + /// /// Gets the P. /// @@ -78,7 +81,6 @@ public override int KeyLength } } - private DsaDigitalSignature _digitalSignature; /// /// Gets the digital signature. /// @@ -86,10 +88,7 @@ protected override DigitalSignature DigitalSignature { get { - if (_digitalSignature == null) - { - _digitalSignature = new DsaDigitalSignature(this); - } + _digitalSignature ??= new DsaDigitalSignature(this); return _digitalSignature; } } @@ -109,7 +108,9 @@ public override BigInteger[] Public set { if (value.Length != 4) + { throw new InvalidOperationException("Invalid public key."); + } _privateKey = value; } @@ -131,7 +132,9 @@ public DsaKey(byte[] data) : base(data) { if (_privateKey.Length != 5) + { throw new InvalidOperationException("Invalid private key."); + } } /// @@ -152,16 +155,12 @@ public DsaKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y, BigInteger _privateKey[4] = x; } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -172,7 +171,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -188,14 +189,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~DsaKey() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/Security/Cryptography/ED25519DigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/ED25519DigitalSignature.cs index be68fd481..4e32772e2 100644 --- a/src/Renci.SshNet/Security/Cryptography/ED25519DigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/ED25519DigitalSignature.cs @@ -10,6 +10,7 @@ namespace Renci.SshNet.Security.Cryptography public class ED25519DigitalSignature : DigitalSignature, IDisposable { private readonly ED25519Key _key; + private bool _isDisposed; /// /// Initializes a new instance of the class. @@ -19,7 +20,9 @@ public class ED25519DigitalSignature : DigitalSignature, IDisposable public ED25519DigitalSignature(ED25519Key key) { if (key == null) - throw new ArgumentNullException("key"); + { + throw new ArgumentNullException(nameof(key)); + } _key = key; } @@ -51,16 +54,12 @@ public override byte[] Sign(byte[] input) return Ed25519.Sign(input, _key.PrivateKey); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -71,7 +70,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -80,14 +81,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~ED25519DigitalSignature() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs index 15f1cb019..8e0862f4d 100644 --- a/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/ED25519Key.cs @@ -1,19 +1,21 @@ using System; + using Renci.SshNet.Common; -using Renci.SshNet.Security.Cryptography; using Renci.SshNet.Security.Chaos.NaCl; +using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet.Security { /// - /// Contains ED25519 private and public key + /// Contains ED25519 private and public key. /// public class ED25519Key : Key, IDisposable { private ED25519DigitalSignature _digitalSignature; private byte[] publicKey = new byte[Ed25519.PublicKeySizeInBytes]; - private byte[] privateKey = new byte[Ed25519.ExpandedPrivateKeySizeInBytes]; + private readonly byte[] privateKey = new byte[Ed25519.ExpandedPrivateKeySizeInBytes]; + private bool _isDisposed; /// /// Gets the Key String. @@ -62,16 +64,13 @@ protected override DigitalSignature DigitalSignature { get { - if (_digitalSignature == null) - { - _digitalSignature = new ED25519DigitalSignature(this); - } + _digitalSignature ??= new ED25519DigitalSignature(this); return _digitalSignature; } } /// - /// Gets the PublicKey Bytes + /// Gets the PublicKey Bytes. /// public byte[] PublicKey { @@ -82,7 +81,7 @@ public byte[] PublicKey } /// - /// Gets the PrivateKey Bytes + /// Gets the PrivateKey Bytes. /// public byte[] PrivateKey { @@ -121,16 +120,12 @@ public ED25519Key(byte[] pk, byte[] sk) Ed25519.KeyPairFromSeed(out publicKey, out privateKey, seed); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -141,7 +136,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -150,14 +147,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~ED25519Key() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs index b5561b5da..e358c1ecf 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaDigitalSignature.cs @@ -1,7 +1,10 @@ using System; -using Renci.SshNet.Common; using System.Globalization; +#if NETFRAMEWORK using System.Security.Cryptography; +#endif // NETFRAMEWORK + +using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography { @@ -11,6 +14,7 @@ namespace Renci.SshNet.Security.Cryptography public class EcdsaDigitalSignature : DigitalSignature, IDisposable { private readonly EcdsaKey _key; + private bool _isDisposed; /// /// Initializes a new instance of the class. @@ -20,7 +24,9 @@ public class EcdsaDigitalSignature : DigitalSignature, IDisposable public EcdsaDigitalSignature(EcdsaKey key) { if (key == null) - throw new ArgumentNullException("key"); + { + throw new ArgumentNullException(nameof(key)); + } _key = key; } @@ -63,21 +69,16 @@ public override byte[] Sign(byte[] input) #else var signed = _key.Ecdsa.SignData(input, _key.HashAlgorithm); #endif - var ssh_data = new SshDataSignature(signed.Length); - ssh_data.Signature = signed; + var ssh_data = new SshDataSignature(signed.Length) { Signature = signed }; return ssh_data.GetBytes(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } @@ -88,7 +89,9 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -97,20 +100,17 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~EcdsaDigitalSignature() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } - class SshDataSignature : SshData + internal class SshDataSignature : SshData { - private int _signature_size; + private readonly int _signature_size; private byte[] _signature_r; private byte[] _signature_s; diff --git a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs index 1674a6677..0a5da1963 100644 --- a/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/EcdsaKey.cs @@ -1,15 +1,20 @@ using System; +#if NETFRAMEWORK using System.IO; +#endif // NETFRAMEWORK using System.Text; +#if NETFRAMEWORK using System.Runtime.InteropServices; +#endif // NETFRAMEWORK using System.Security.Cryptography; + using Renci.SshNet.Common; using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet.Security { /// - /// Contains ECDSA (ecdsa-sha2-nistp{256,384,521}) private and public key + /// Contains ECDSA (ecdsa-sha2-nistp{256,384,521}) private and public key. /// public class EcdsaKey : Key, IDisposable { @@ -17,6 +22,9 @@ public class EcdsaKey : Key, IDisposable internal const string ECDSA_P384_OID_VALUE = "1.3.132.0.34"; // Also called nistP384 or secP384r1 internal const string ECDSA_P521_OID_VALUE = "1.3.132.0.35"; // Also called nistP521or secP521r1 + private EcdsaDigitalSignature _digitalSignature; + private bool _isDisposed; + #if NETFRAMEWORK internal enum KeyBlobMagicNumber : int { @@ -49,8 +57,11 @@ internal struct BCRYPT_ECCKEY_BLOB #endif /// - /// Gets the SSH name of the ECDSA Key + /// Gets the SSH name of the ECDSA Key. /// + /// + /// The SSH name of the ECDSA Key. + /// public override string ToString() { return string.Format("ecdsa-sha2-nistp{0}", KeyLength); @@ -79,7 +90,7 @@ public CngAlgorithm HashAlgorithm } #else /// - /// Gets the HashAlgorithm to use + /// Gets the HashAlgorithm to use. /// public HashAlgorithmName HashAlgorithm { @@ -94,6 +105,7 @@ public HashAlgorithmName HashAlgorithm case 521: return HashAlgorithmName.SHA512; } + return HashAlgorithmName.SHA256; } } @@ -113,8 +125,6 @@ public override int KeyLength } } - private EcdsaDigitalSignature _digitalSignature; - /// /// Gets the digital signature. /// @@ -122,10 +132,8 @@ protected override DigitalSignature DigitalSignature { get { - if (_digitalSignature == null) - { - _digitalSignature = new EcdsaDigitalSignature(this); - } + _digitalSignature ??= new EcdsaDigitalSignature(this); + return _digitalSignature; } } @@ -150,7 +158,7 @@ public override BigInteger[] Public using (var br = new BinaryReader(new MemoryStream(blob))) { magic = (KeyBlobMagicNumber)br.ReadInt32(); - int cbKey = br.ReadInt32(); + var cbKey = br.ReadInt32(); qx = br.ReadBytes(cbKey); qy = br.ReadBytes(cbKey); } @@ -191,6 +199,7 @@ public override BigInteger[] Public throw new SshException("Unexpected Curve Name: " + parameter.Curve.Oid.FriendlyName); } #endif + // Make ECPoint from x and y // Prepend 04 (uncompressed format) + qx-bytes + qy-bytes var q = new byte[1 + qx.Length + qy.Length]; @@ -204,7 +213,7 @@ public override BigInteger[] Public set { var curve_s = Encoding.ASCII.GetString(value[0].ToByteArray().Reverse()); - string curve_oid = GetCurveOid(curve_s); + var curve_oid = GetCurveOid(curve_s); var publickey = value[1].ToByteArray().Reverse(); Import(curve_oid, publickey, null); @@ -212,12 +221,12 @@ public override BigInteger[] Public } /// - /// Gets the PrivateKey Bytes + /// Gets the PrivateKey Bytes. /// public byte[] PrivateKey { get; private set; } /// - /// Gets ECDsa Object + /// Gets the object. /// public ECDsa Ecdsa { get; private set; } @@ -231,9 +240,9 @@ public EcdsaKey() /// /// Initializes a new instance of the class. /// - /// The curve name - /// Value of publickey - /// Value of privatekey + /// The curve name. + /// Value of publickey. + /// Value of privatekey. public EcdsaKey(string curve, byte[] publickey, byte[] privatekey) { Import(GetCurveOid(curve), publickey, privatekey); @@ -246,7 +255,7 @@ public EcdsaKey(string curve, byte[] publickey, byte[] privatekey) public EcdsaKey(byte[] data) { var der = new DerData(data); - var version = der.ReadBigInteger(); // skip version + _ = der.ReadBigInteger(); // skip version // PrivateKey var privatekey = der.ReadOctetString().TrimLeadingZeros(); @@ -254,10 +263,16 @@ public EcdsaKey(byte[] data) // Construct var s0 = der.ReadByte(); if ((s0 & 0xe0) != 0xa0) + { throw new SshException(string.Format("UnexpectedDER: wanted constructed tag (0xa0-0xbf), got: {0:X}", s0)); + } + var tag = s0 & 0x1f; if (tag != 0) + { throw new SshException(string.Format("expected tag 0 in DER privkey, got: {0}", tag)); + } + var construct = der.ReadBytes(der.ReadLength()); // object length // curve OID @@ -267,10 +282,16 @@ public EcdsaKey(byte[] data) // Construct s0 = der.ReadByte(); if ((s0 & 0xe0) != 0xa0) + { throw new SshException(string.Format("UnexpectedDER: wanted constructed tag (0xa0-0xbf), got: {0:X}", s0)); + } + tag = s0 & 0x1f; if (tag != 1) + { throw new SshException(string.Format("expected tag 1 in DER privkey, got: {0}", tag)); + } + construct = der.ReadBytes(der.ReadLength()); // object length // PublicKey @@ -288,21 +309,36 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) { case "nistp256": if (privatekey != null) + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P256_MAGIC; + } else + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P256_MAGIC; + } + break; case "nistp384": if (privatekey != null) + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P384_MAGIC; + } else + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P384_MAGIC; + } + break; case "nistp521": if (privatekey != null) + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PRIVATE_P521_MAGIC; + } else + { curve_magic = KeyBlobMagicNumber.BCRYPT_ECDSA_PUBLIC_P521_MAGIC; + } + break; default: throw new SshException("Unknown: " + curve_oid); @@ -322,12 +358,14 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) PrivateKey = privatekey; } - int headerSize = Marshal.SizeOf(typeof(BCRYPT_ECCKEY_BLOB)); - int blobSize = headerSize + qx.Length + qy.Length; + var headerSize = Marshal.SizeOf(typeof(BCRYPT_ECCKEY_BLOB)); + var blobSize = headerSize + qx.Length + qy.Length; if (privatekey != null) + { blobSize += privatekey.Length; + } - byte[] blob = new byte[blobSize]; + var blob = new byte[blobSize]; using (var bw = new BinaryWriter(new MemoryStream(blob))) { bw.Write((int)curve_magic); @@ -335,7 +373,9 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) bw.Write(qx); // q.x bw.Write(qy); // q.y if (privatekey != null) + { bw.Write(privatekey); // d + } } key = CngKey.Import(blob, privatekey == null ? CngKeyBlobFormat.EccPublicBlob : CngKeyBlobFormat.EccPrivateBlob); @@ -368,7 +408,7 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey) #endif } - private string GetCurveOid(string curve_s) + private static string GetCurveOid(string curve_s) { switch (curve_s.ToLower()) { @@ -383,6 +423,7 @@ private string GetCurveOid(string curve_s) } } +#if NETFRAMEWORK private string GetCurveName(string oid) { switch (oid) @@ -397,27 +438,29 @@ private string GetCurveName(string oid) throw new SshException("Unexpected OID: " + oid); } } +#endif // NETFRAMEWORK - private string OidByteArrayToString(byte[] oid) + private static string OidByteArrayToString(byte[] oid) { - StringBuilder retVal = new StringBuilder(); + var retVal = new StringBuilder(); - for (int i = 0; i < oid.Length; i++) + for (var i = 0; i < oid.Length; i++) { if (i == 0) { - int b = oid[0] % 40; - int a = (oid[0] - b) / 40; - retVal.AppendFormat("{0}.{1}", a, b); + var b = oid[0] % 40; + var a = (oid[0] - b) / 40; + _ = retVal.AppendFormat("{0}.{1}", a, b); } else { if (oid[i] < 128) - retVal.AppendFormat(".{0}", oid[i]); + { + _ = retVal.AppendFormat(".{0}", oid[i]); + } else { - retVal.AppendFormat(".{0}", - ((oid[i] - 128) * 128) + oid[i + 1]); + _ = retVal.AppendFormat(".{0}", ((oid[i] - 128) * 128) + oid[i + 1]); i++; } } @@ -426,27 +469,25 @@ private string OidByteArrayToString(byte[] oid) return retVal.ToString(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -455,14 +496,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~EcdsaKey() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs b/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs index 49ad384d4..05a9730ed 100644 --- a/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs +++ b/src/Renci.SshNet/Security/Cryptography/HMACSHA1.cs @@ -1,4 +1,5 @@ using System.Security.Cryptography; + using Renci.SshNet.Common; namespace Renci.SshNet.Security.Cryptography @@ -11,7 +12,7 @@ public class HMACSHA1 : System.Security.Cryptography.HMACSHA1 private readonly int _hashSize; /// - /// Initializes a with the specified key. + /// Initializes a new instance of the class with the specified key. /// /// The key. public HMACSHA1(byte[] key) @@ -21,7 +22,7 @@ public HMACSHA1(byte[] key) } /// - /// Initializes a with the specified key and size of the computed hash code. + /// Initializes a new instance of the class with the specified key and size of the computed hash code. /// /// The key. /// The size, in bits, of the computed hash code. diff --git a/src/Renci.SshNet/Security/Cryptography/Key.cs b/src/Renci.SshNet/Security/Cryptography/Key.cs index 61c5150c2..6f5a6312b 100644 --- a/src/Renci.SshNet/Security/Cryptography/Key.cs +++ b/src/Renci.SshNet/Security/Cryptography/Key.cs @@ -1,17 +1,18 @@ using System; using System.Collections.Generic; + using Renci.SshNet.Common; using Renci.SshNet.Security.Cryptography; namespace Renci.SshNet.Security { /// - /// Base class for asymmetric cipher algorithms + /// Base class for asymmetric cipher algorithms. /// public abstract class Key { /// - /// Specifies array of big integers that represent private key + /// Specifies array of big integers that represent private key. /// protected BigInteger[] _privateKey; @@ -37,7 +38,7 @@ public abstract class Key public abstract int KeyLength { get; } /// - /// Gets the Key Comment + /// Gets or sets the key comment. /// public string Comment { get; set; } @@ -48,10 +49,12 @@ public abstract class Key protected Key(byte[] data) { if (data == null) - throw new ArgumentNullException("data"); + { + throw new ArgumentNullException(nameof(data)); + } var der = new DerData(data); - der.ReadBigInteger(); // skip version + _ = der.ReadBigInteger(); // skip version var keys = new List(); while (!der.IsEndOfData) diff --git a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs index ba5b17464..b80e4302c 100644 --- a/src/Renci.SshNet/Security/Cryptography/RsaKey.cs +++ b/src/Renci.SshNet/Security/Cryptography/RsaKey.cs @@ -174,7 +174,6 @@ public override BigInteger[] Public /// public RsaKey() { - } /// @@ -212,7 +211,7 @@ public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger private static BigInteger PrimeExponent(BigInteger privateExponent, BigInteger prime) { - BigInteger pe = prime - new BigInteger(1); + var pe = prime - new BigInteger(1); return privateExponent % pe; } diff --git a/src/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs b/src/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs index a1c8a2a90..f4e35c375 100644 --- a/src/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs +++ b/src/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs @@ -20,7 +20,9 @@ public abstract class SymmetricCipher : Cipher protected SymmetricCipher(byte[] key) { if (key == null) - throw new ArgumentNullException("key"); + { + throw new ArgumentNullException(nameof(key)); + } Key = key; } diff --git a/src/Renci.SshNet/Security/IKeyExchange.cs b/src/Renci.SshNet/Security/IKeyExchange.cs index b6f9bb080..f12a18322 100644 --- a/src/Renci.SshNet/Security/IKeyExchange.cs +++ b/src/Renci.SshNet/Security/IKeyExchange.cs @@ -1,5 +1,6 @@ using System; using System.Security.Cryptography; + using Renci.SshNet.Common; using Renci.SshNet.Compression; using Renci.SshNet.Messages.Transport; diff --git a/src/Renci.SshNet/Security/KeyExchange.cs b/src/Renci.SshNet/Security/KeyExchange.cs index a13c272a6..92a61973f 100644 --- a/src/Renci.SshNet/Security/KeyExchange.cs +++ b/src/Renci.SshNet/Security/KeyExchange.cs @@ -24,7 +24,7 @@ public abstract class KeyExchange : Algorithm, IKeyExchange private Type _decompressionType; /// - /// Gets or sets the session. + /// Gets the session. /// /// /// The session. @@ -53,6 +53,7 @@ public byte[] ExchangeHash { _exchangeHash = CalculateHash(); } + return _exchangeHash; } } @@ -63,7 +64,7 @@ public byte[] ExchangeHash public event EventHandler HostKeyReceived; /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -73,7 +74,7 @@ public virtual void Start(Session session, KeyExchangeInitMessage message) SendMessage(session.ClientInitMessage); - // Determine encryption algorithm + // Determine encryption algorithm var clientEncryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys from a in message.EncryptionAlgorithmsClientToServer where a == b @@ -86,7 +87,7 @@ from a in message.EncryptionAlgorithmsClientToServer session.ConnectionInfo.CurrentClientEncryption = clientEncryptionAlgorithmName; - // Determine encryption algorithm + // Determine encryption algorithm var serverDecryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys from a in message.EncryptionAlgorithmsServerToClient where a == b @@ -98,7 +99,7 @@ from a in message.EncryptionAlgorithmsServerToClient session.ConnectionInfo.CurrentServerEncryption = serverDecryptionAlgorithmName; - // Determine client hmac algorithm + // Determine client hmac algorithm var clientHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys from a in message.MacAlgorithmsClientToServer where a == b @@ -110,7 +111,7 @@ from a in message.MacAlgorithmsClientToServer session.ConnectionInfo.CurrentClientHmacAlgorithm = clientHmacAlgorithmName; - // Determine server hmac algorithm + // Determine server hmac algorithm var serverHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys from a in message.MacAlgorithmsServerToClient where a == b @@ -122,7 +123,7 @@ from a in message.MacAlgorithmsServerToClient session.ConnectionInfo.CurrentServerHmacAlgorithm = serverHmacAlgorithmName; - // Determine compression algorithm + // Determine compression algorithm var compressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys from a in message.CompressionAlgorithmsClientToServer where a == b @@ -134,7 +135,7 @@ from a in message.CompressionAlgorithmsClientToServer session.ConnectionInfo.CurrentClientCompressionAlgorithm = compressionAlgorithmName; - // Determine decompression algorithm + // Determine decompression algorithm var decompressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys from a in message.CompressionAlgorithmsServerToClient where a == b @@ -159,15 +160,12 @@ from a in message.CompressionAlgorithmsServerToClient /// public virtual void Finish() { - // Validate hash - if (ValidateExchangeHash()) - { - SendMessage(new NewKeysMessage()); - } - else + if (!ValidateExchangeHash()) { throw new SshConnectionException("Key exchange negotiation failed.", DisconnectReason.KeyExchangeFailed); } + + SendMessage(new NewKeysMessage()); } /// @@ -176,13 +174,13 @@ public virtual void Finish() /// Server cipher. public Cipher CreateServerCipher() { - // Resolve Session ID + // Resolve Session ID var sessionId = Session.SessionId ?? ExchangeHash; - // Calculate server to client initial IV + // Calculate server to client initial IV var serverVector = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'B', sessionId)); - // Calculate server to client encryption + // Calculate server to client encryption var serverKey = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'D', sessionId)); serverKey = GenerateSessionKey(SharedKey, ExchangeHash, serverKey, _serverCipherInfo.KeySize / 8); @@ -193,7 +191,7 @@ public Cipher CreateServerCipher() Session.ToHex(serverKey), Session.ToHex(serverVector))); - // Create server cipher + // Create server cipher return _serverCipherInfo.Cipher(serverKey, serverVector); } @@ -203,63 +201,71 @@ public Cipher CreateServerCipher() /// Client cipher. public Cipher CreateClientCipher() { - // Resolve Session ID + // Resolve Session ID var sessionId = Session.SessionId ?? ExchangeHash; - // Calculate client to server initial IV + // Calculate client to server initial IV var clientVector = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'A', sessionId)); - // Calculate client to server encryption + // Calculate client to server encryption var clientKey = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'C', sessionId)); clientKey = GenerateSessionKey(SharedKey, ExchangeHash, clientKey, _clientCipherInfo.KeySize / 8); - // Create client cipher + // Create client cipher return _clientCipherInfo.Cipher(clientKey, clientVector); } /// /// Creates the server side hash algorithm to use. /// - /// Hash algorithm + /// + /// The server-side hash algorithm. + /// public HashAlgorithm CreateServerHash() { - // Resolve Session ID + // Resolve Session ID var sessionId = Session.SessionId ?? ExchangeHash; - var serverKey = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'F', sessionId)); + var serverKey = GenerateSessionKey(SharedKey, + ExchangeHash, + Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'F', sessionId)), + _serverHashInfo.KeySize / 8); - serverKey = GenerateSessionKey(SharedKey, ExchangeHash, serverKey, _serverHashInfo.KeySize / 8); - - //return serverHMac; return _serverHashInfo.HashAlgorithm(serverKey); } /// /// Creates the client side hash algorithm to use. /// - /// Hash algorithm + /// + /// The client-side hash algorithm. + /// public HashAlgorithm CreateClientHash() { - // Resolve Session ID + // Resolve Session ID var sessionId = Session.SessionId ?? ExchangeHash; - var clientKey = Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'E', sessionId)); - - clientKey = GenerateSessionKey(SharedKey, ExchangeHash, clientKey, _clientHashInfo.KeySize / 8); + var clientKey = GenerateSessionKey(SharedKey, + ExchangeHash, + Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'E', sessionId)), + _clientHashInfo.KeySize / 8); - //return clientHMac; return _clientHashInfo.HashAlgorithm(clientKey); } /// /// Creates the compression algorithm to use to deflate data. /// - /// Compression method. + /// + /// The compression method. + /// public Compressor CreateCompressor() { if (_compressionType == null) + { return null; + } var compressor = _compressionType.CreateInstance(); @@ -271,11 +277,15 @@ public Compressor CreateCompressor() /// /// Creates the compression algorithm to use to inflate data. /// - /// Compression method. + /// + /// The decompression method. + /// public Compressor CreateDecompressor() { - if (_compressionType == null) + if (_decompressionType == null) + { return null; + } var decompressor = _decompressionType.CreateInstance(); @@ -321,12 +331,12 @@ protected bool CanTrustHostKey(KeyHostAlgorithm host) /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected abstract byte[] Hash(byte[] hashData); /// - /// Sends SSH message to the server + /// Sends SSH message to the server. /// /// The message. protected void SendMessage(Message message) @@ -341,7 +351,9 @@ protected void SendMessage(Message message) /// The exchange hash. /// The key. /// The size. - /// + /// + /// The session key. + /// private byte[] GenerateSessionKey(byte[] sharedKey, byte[] exchangeHash, byte[] key, int size) { var result = new List(key); @@ -368,7 +380,9 @@ private byte[] GenerateSessionKey(byte[] sharedKey, byte[] exchangeHash, byte[] /// The exchange hash. /// The p. /// The session id. - /// + /// + /// The session key. + /// private static byte[] GenerateSessionKey(byte[] sharedKey, byte[] exchangeHash, char p, byte[] sessionId) { var sessionKeyGeneration = new SessionKeyGeneration @@ -381,7 +395,7 @@ private static byte[] GenerateSessionKey(byte[] sharedKey, byte[] exchangeHash, return sessionKeyGeneration.GetBytes(); } - private class SessionKeyGeneration : SshData + private sealed class SessionKeyGeneration : SshData { public byte[] SharedKey { get; set; } @@ -425,7 +439,7 @@ protected override void SaveData() } } - private class SessionKeyAdjustment : SshData + private sealed class SessionKeyAdjustment : SshData { public byte[] SharedKey { get; set; } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs index 375c3a59d..836c607f3 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs @@ -1,7 +1,8 @@ using System; using System.Text; -using Renci.SshNet.Messages.Transport; + using Renci.SshNet.Common; +using Renci.SshNet.Messages.Transport; namespace Renci.SshNet.Security { @@ -21,7 +22,7 @@ internal abstract class KeyExchangeDiffieHellman : KeyExchange protected BigInteger _prime; /// - /// Specifies client payload + /// Specifies client payload. /// protected byte[] _clientPayload; @@ -83,11 +84,12 @@ protected override bool ValidateExchangeHash() { return key.VerifySignature(exchangeHash, _signature); } + return false; } /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -105,10 +107,14 @@ public override void Start(Session session, KeyExchangeInitMessage message) protected void PopulateClientExchangeValue() { if (_group.IsZero) + { throw new ArgumentNullException("_group"); + } if (_prime.IsZero) + { throw new ArgumentNullException("_prime"); + } // generate private exponent that is twice the hash size (RFC 4419) with a minimum // of 1024 bits (whatever is less) @@ -118,11 +124,13 @@ protected void PopulateClientExchangeValue() do { - // create private component + // Create private component _privateExponent = BigInteger.Random(privateExponentSize); - // generate public component + + // Generate public component clientExchangeValue = BigInteger.ModPow(_group, _privateExponent, _prime); - } while (clientExchangeValue < 1 || clientExchangeValue > (_prime - 1)); + } + while (clientExchangeValue < 1 || clientExchangeValue > (_prime - 1)); _clientExchangeValue = clientExchangeValue.ToByteArray().Reverse(); } diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs index ec7a237dd..be0bfe745 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs @@ -5,10 +5,10 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group14-sha1" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroup14Sha1 : KeyExchangeDiffieHellmanGroupSha1 + internal sealed class KeyExchangeDiffieHellmanGroup14Sha1 : KeyExchangeDiffieHellmanGroupSha1 { /// - /// https://tools.ietf.org/html/rfc2409#section-6.2 + /// Defined in https://tools.ietf.org/html/rfc2409#section-6.2. /// private static readonly byte[] SecondOkleyGroupReversed = { @@ -59,4 +59,4 @@ public override BigInteger GroupPrime } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs index 276077a09..9687875e7 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha256.cs @@ -5,10 +5,10 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group14-sha256" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroup14Sha256 : KeyExchangeDiffieHellmanGroupSha256 + internal sealed class KeyExchangeDiffieHellmanGroup14Sha256 : KeyExchangeDiffieHellmanGroupSha256 { /// - /// https://tools.ietf.org/html/rfc2409#section-6.2 + /// Defined in https://tools.ietf.org/html/rfc2409#section-6.2. /// private static readonly byte[] SecondOkleyGroupReversed = { @@ -59,4 +59,4 @@ public override BigInteger GroupPrime } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs index 48f7e178a..ba8403fec 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup16Sha512.cs @@ -5,45 +5,45 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group16-sha512" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroup16Sha512 : KeyExchangeDiffieHellmanGroupSha512 + internal sealed class KeyExchangeDiffieHellmanGroup16Sha512 : KeyExchangeDiffieHellmanGroupSha512 { /// - /// https://tools.ietf.org/html/rfc3526#section-5 + /// Defined in https://tools.ietf.org/html/rfc3526#section-5. /// private static readonly byte[] MoreModularExponentialGroup16Reversed = { - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x99,0x31,0x06,0x34,0xc9,0x35,0xf4,0x4d, - 0x8f,0xc0,0xa6,0x90,0xdc,0xb7,0xff,0x86,0xc1,0xdd,0x8f,0x8d,0x98,0xea,0xb4,0x93, - 0xa9,0x5a,0xb0,0xd5,0x27,0x91,0x06,0xd0,0x1c,0x48,0x70,0x21,0x76,0xdd,0x1b,0xb8, - 0xaf,0xd7,0xe2,0xce,0x70,0x29,0x61,0x1f,0xed,0xe7,0x5b,0x51,0x86,0xa1,0x3b,0x23, - 0xa2,0xc3,0x90,0xa0,0x4f,0x96,0xb2,0x99,0x5d,0xc0,0x6b,0x4e,0x47,0x59,0x7c,0x28, - 0xa6,0xca,0xbe,0x1f,0x14,0xfc,0x8e,0x2e,0xf9,0x8e,0xde,0x04,0xdb,0xc2,0xbb,0xdb, - 0xe8,0x4c,0xd4,0x2a,0xca,0xe9,0x83,0x25,0xda,0x0b,0x15,0xb6,0x34,0x68,0x94,0x1a, - 0x3c,0xe2,0xf4,0x6a,0x18,0x27,0xc3,0x99,0x26,0x5b,0xba,0xbd,0x10,0x9a,0x71,0x88, - 0xd7,0xe6,0x87,0xa7,0x12,0x3c,0x72,0x1a,0x01,0x08,0x21,0xa9,0x20,0xd1,0x82,0x4b, - 0x8e,0x10,0xfd,0xe0,0xfc,0x5b,0xdb,0x43,0x31,0xab,0xe5,0x74,0xa0,0x4f,0xe2,0x08, - 0xe2,0x46,0xd9,0xba,0xc0,0x88,0x09,0x77,0x6c,0x5d,0x61,0x7a,0x57,0x17,0xe1,0xbb, - 0x0c,0x20,0x7b,0x17,0x18,0x2b,0x1f,0x52,0x64,0x6a,0xc8,0x3e,0x73,0x02,0x76,0xd8, - 0x64,0x08,0x8a,0xd9,0x06,0xfa,0x2f,0xf1,0x6b,0xee,0xd2,0x1a,0x26,0xd2,0xe3,0xce, - 0x9d,0x61,0x25,0x4a,0xe0,0x94,0x8c,0x1e,0xd7,0x33,0x09,0xdb,0x8c,0xae,0xf5,0xab, - 0xc7,0xe4,0xe1,0xa6,0x85,0x0f,0x97,0xb3,0x7d,0x0c,0x06,0x5d,0x57,0x71,0xea,0x8a, - 0x0a,0xef,0xdb,0x58,0x04,0x85,0xfb,0xec,0x64,0xba,0x1c,0xdf,0xab,0x21,0x55,0xa8, - 0x33,0x7a,0x50,0x04,0x0d,0x17,0x33,0xad,0x2d,0xc4,0xaa,0x8a,0x5a,0x8e,0x72,0x15, - 0x10,0x05,0xfa,0x98,0x18,0x26,0xd2,0x15,0xe5,0x6a,0x95,0xea,0x7c,0x49,0x95,0x39, - 0x18,0x17,0x58,0x95,0xf6,0xcb,0x2b,0xde,0xc9,0x52,0x4c,0x6f,0xf0,0x5d,0xc5,0xb5, - 0x8f,0xa2,0x07,0xec,0xa2,0x83,0x27,0x9b,0x03,0x86,0x0e,0x18,0x2c,0x77,0x9e,0xe3, - 0x3b,0xce,0x36,0x2e,0x46,0x5e,0x90,0x32,0x7c,0x21,0x18,0xca,0x08,0x6c,0x74,0xf1, - 0x04,0x98,0xbc,0x4a,0x4e,0x35,0x0c,0x67,0x6d,0x96,0x96,0x70,0x07,0x29,0xd5,0x9e, - 0xbb,0x52,0x85,0x20,0x56,0xf3,0x62,0x1c,0x96,0xad,0xa3,0xdc,0x23,0x5d,0x65,0x83, - 0x5f,0xcf,0x24,0xfd,0xa8,0x3f,0x16,0x69,0x9a,0xd3,0x55,0x1c,0x36,0x48,0xda,0x98, - 0x05,0xbf,0x63,0xa1,0xb8,0x7c,0x00,0xc2,0x3d,0x5b,0xe4,0xec,0x51,0x66,0x28,0x49, - 0xe6,0x1f,0x4b,0x7c,0x11,0x24,0x9f,0xae,0xa5,0x9f,0x89,0x5a,0xfb,0x6b,0x38,0xee, - 0xed,0xb7,0x06,0xf4,0xb6,0x5c,0xff,0x0b,0x6b,0xed,0x37,0xa6,0xe9,0x42,0x4c,0xf4, - 0xc6,0x7e,0x5e,0x62,0x76,0xb5,0x85,0xe4,0x45,0xc2,0x51,0x6d,0x6d,0x35,0xe1,0x4f, - 0x37,0x14,0x5f,0xf2,0x6d,0x0a,0x2b,0x30,0x1b,0x43,0x3a,0xcd,0xb3,0x19,0x95,0xef, - 0xdd,0x04,0x34,0x8e,0x79,0x08,0x4a,0x51,0x22,0x9b,0x13,0x3b,0xa6,0xbe,0x0b,0x02, - 0x74,0xcc,0x67,0x8a,0x08,0x4e,0x02,0x29,0xd1,0x1c,0xdc,0x80,0x8b,0x62,0xc6,0xc4, - 0x34,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0x31, 0x06, 0x34, 0xc9, 0x35, 0xf4, 0x4d, + 0x8f, 0xc0, 0xa6, 0x90, 0xdc, 0xb7, 0xff, 0x86, 0xc1, 0xdd, 0x8f, 0x8d, 0x98, 0xea, 0xb4, 0x93, + 0xa9, 0x5a, 0xb0, 0xd5, 0x27, 0x91, 0x06, 0xd0, 0x1c, 0x48, 0x70, 0x21, 0x76, 0xdd, 0x1b, 0xb8, + 0xaf, 0xd7, 0xe2, 0xce, 0x70, 0x29, 0x61, 0x1f, 0xed, 0xe7, 0x5b, 0x51, 0x86, 0xa1, 0x3b, 0x23, + 0xa2, 0xc3, 0x90, 0xa0, 0x4f, 0x96, 0xb2, 0x99, 0x5d, 0xc0, 0x6b, 0x4e, 0x47, 0x59, 0x7c, 0x28, + 0xa6, 0xca, 0xbe, 0x1f, 0x14, 0xfc, 0x8e, 0x2e, 0xf9, 0x8e, 0xde, 0x04, 0xdb, 0xc2, 0xbb, 0xdb, + 0xe8, 0x4c, 0xd4, 0x2a, 0xca, 0xe9, 0x83, 0x25, 0xda, 0x0b, 0x15, 0xb6, 0x34, 0x68, 0x94, 0x1a, + 0x3c, 0xe2, 0xf4, 0x6a, 0x18, 0x27, 0xc3, 0x99, 0x26, 0x5b, 0xba, 0xbd, 0x10, 0x9a, 0x71, 0x88, + 0xd7, 0xe6, 0x87, 0xa7, 0x12, 0x3c, 0x72, 0x1a, 0x01, 0x08, 0x21, 0xa9, 0x20, 0xd1, 0x82, 0x4b, + 0x8e, 0x10, 0xfd, 0xe0, 0xfc, 0x5b, 0xdb, 0x43, 0x31, 0xab, 0xe5, 0x74, 0xa0, 0x4f, 0xe2, 0x08, + 0xe2, 0x46, 0xd9, 0xba, 0xc0, 0x88, 0x09, 0x77, 0x6c, 0x5d, 0x61, 0x7a, 0x57, 0x17, 0xe1, 0xbb, + 0x0c, 0x20, 0x7b, 0x17, 0x18, 0x2b, 0x1f, 0x52, 0x64, 0x6a, 0xc8, 0x3e, 0x73, 0x02, 0x76, 0xd8, + 0x64, 0x08, 0x8a, 0xd9, 0x06, 0xfa, 0x2f, 0xf1, 0x6b, 0xee, 0xd2, 0x1a, 0x26, 0xd2, 0xe3, 0xce, + 0x9d, 0x61, 0x25, 0x4a, 0xe0, 0x94, 0x8c, 0x1e, 0xd7, 0x33, 0x09, 0xdb, 0x8c, 0xae, 0xf5, 0xab, + 0xc7, 0xe4, 0xe1, 0xa6, 0x85, 0x0f, 0x97, 0xb3, 0x7d, 0x0c, 0x06, 0x5d, 0x57, 0x71, 0xea, 0x8a, + 0x0a, 0xef, 0xdb, 0x58, 0x04, 0x85, 0xfb, 0xec, 0x64, 0xba, 0x1c, 0xdf, 0xab, 0x21, 0x55, 0xa8, + 0x33, 0x7a, 0x50, 0x04, 0x0d, 0x17, 0x33, 0xad, 0x2d, 0xc4, 0xaa, 0x8a, 0x5a, 0x8e, 0x72, 0x15, + 0x10, 0x05, 0xfa, 0x98, 0x18, 0x26, 0xd2, 0x15, 0xe5, 0x6a, 0x95, 0xea, 0x7c, 0x49, 0x95, 0x39, + 0x18, 0x17, 0x58, 0x95, 0xf6, 0xcb, 0x2b, 0xde, 0xc9, 0x52, 0x4c, 0x6f, 0xf0, 0x5d, 0xc5, 0xb5, + 0x8f, 0xa2, 0x07, 0xec, 0xa2, 0x83, 0x27, 0x9b, 0x03, 0x86, 0x0e, 0x18, 0x2c, 0x77, 0x9e, 0xe3, + 0x3b, 0xce, 0x36, 0x2e, 0x46, 0x5e, 0x90, 0x32, 0x7c, 0x21, 0x18, 0xca, 0x08, 0x6c, 0x74, 0xf1, + 0x04, 0x98, 0xbc, 0x4a, 0x4e, 0x35, 0x0c, 0x67, 0x6d, 0x96, 0x96, 0x70, 0x07, 0x29, 0xd5, 0x9e, + 0xbb, 0x52, 0x85, 0x20, 0x56, 0xf3, 0x62, 0x1c, 0x96, 0xad, 0xa3, 0xdc, 0x23, 0x5d, 0x65, 0x83, + 0x5f, 0xcf, 0x24, 0xfd, 0xa8, 0x3f, 0x16, 0x69, 0x9a, 0xd3, 0x55, 0x1c, 0x36, 0x48, 0xda, 0x98, + 0x05, 0xbf, 0x63, 0xa1, 0xb8, 0x7c, 0x00, 0xc2, 0x3d, 0x5b, 0xe4, 0xec, 0x51, 0x66, 0x28, 0x49, + 0xe6, 0x1f, 0x4b, 0x7c, 0x11, 0x24, 0x9f, 0xae, 0xa5, 0x9f, 0x89, 0x5a, 0xfb, 0x6b, 0x38, 0xee, + 0xed, 0xb7, 0x06, 0xf4, 0xb6, 0x5c, 0xff, 0x0b, 0x6b, 0xed, 0x37, 0xa6, 0xe9, 0x42, 0x4c, 0xf4, + 0xc6, 0x7e, 0x5e, 0x62, 0x76, 0xb5, 0x85, 0xe4, 0x45, 0xc2, 0x51, 0x6d, 0x6d, 0x35, 0xe1, 0x4f, + 0x37, 0x14, 0x5f, 0xf2, 0x6d, 0x0a, 0x2b, 0x30, 0x1b, 0x43, 0x3a, 0xcd, 0xb3, 0x19, 0x95, 0xef, + 0xdd, 0x04, 0x34, 0x8e, 0x79, 0x08, 0x4a, 0x51, 0x22, 0x9b, 0x13, 0x3b, 0xa6, 0xbe, 0x0b, 0x02, + 0x74, 0xcc, 0x67, 0x8a, 0x08, 0x4e, 0x02, 0x29, 0xd1, 0x1c, 0xdc, 0x80, 0x8b, 0x62, 0xc6, 0xc4, + 0x34, 0xc2, 0x68, 0x21, 0xa2, 0xda, 0x0f, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs index 3a8de7f42..d0ff2c01d 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group1-sha1" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroup1Sha1 : KeyExchangeDiffieHellmanGroupSha1 + internal sealed class KeyExchangeDiffieHellmanGroup1Sha1 : KeyExchangeDiffieHellmanGroupSha1 { private static readonly byte[] SecondOkleyGroupReversed = { diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs index a7f1b7420..791e2c44b 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group-exchange-sha1" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroupExchangeSha1 : KeyExchangeDiffieHellmanGroupExchangeShaBase + internal sealed class KeyExchangeDiffieHellmanGroupExchangeSha1 : KeyExchangeDiffieHellmanGroupExchangeShaBase { /// /// Gets algorithm name. @@ -31,7 +31,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs index dca2de712..3302d9a94 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Security /// /// Represents "diffie-hellman-group-exchange-sha256" algorithm implementation. /// - internal class KeyExchangeDiffieHellmanGroupExchangeSha256 : KeyExchangeDiffieHellmanGroupExchangeShaBase + internal sealed class KeyExchangeDiffieHellmanGroupExchangeSha256 : KeyExchangeDiffieHellmanGroupExchangeShaBase { /// /// Gets algorithm name. @@ -31,7 +31,7 @@ protected override int HashSize /// /// Data to hash. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashBytes) { diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs index 755f77f2e..93703ee8f 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeShaBase.cs @@ -40,7 +40,7 @@ protected override byte[] CalculateHash() } /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -50,6 +50,7 @@ public override void Start(Session session, KeyExchangeInitMessage message) // Register SSH_MSG_KEX_DH_GEX_GROUP message Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP"); + // Subscribe to KeyExchangeDhGroupExchangeGroupReceived events Session.KeyExchangeDhGroupExchangeGroupReceived += Session_KeyExchangeDhGroupExchangeGroupReceived; @@ -75,11 +76,13 @@ private void Session_KeyExchangeDhGroupExchangeGroupReceived(object sender, Mess // Unregister SSH_MSG_KEX_DH_GEX_GROUP message once received Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP"); + // Unsubscribe from KeyExchangeDhGroupExchangeGroupReceived events Session.KeyExchangeDhGroupExchangeGroupReceived -= Session_KeyExchangeDhGroupExchangeGroupReceived; // Register in order to be able to receive SSH_MSG_KEX_DH_GEX_REPLY message Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); + // Subscribe to KeyExchangeDhGroupExchangeReplyReceived events Session.KeyExchangeDhGroupExchangeReplyReceived += Session_KeyExchangeDhGroupExchangeReplyReceived; @@ -99,6 +102,7 @@ private void Session_KeyExchangeDhGroupExchangeReplyReceived(object sender, Mess // Unregister SSH_MSG_KEX_DH_GEX_REPLY message once received Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY"); + // Unsubscribe from KeyExchangeDhGroupExchangeReplyReceived events Session.KeyExchangeDhGroupExchangeReplyReceived -= Session_KeyExchangeDhGroupExchangeReplyReceived; diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs index 675ee2cfe..4669eb8ae 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs @@ -23,7 +23,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha256.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha256.cs index 6cb674601..ea29e6e2f 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha256.cs @@ -23,7 +23,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { @@ -33,4 +33,4 @@ protected override byte[] Hash(byte[] hashData) } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha512.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha512.cs index 54369b849..60a8e5f7c 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha512.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha512.cs @@ -23,7 +23,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { @@ -33,4 +33,4 @@ protected override byte[] Hash(byte[] hashData) } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs index 2618b63ac..63c2bba40 100644 --- a/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs +++ b/src/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupShaBase.cs @@ -14,30 +14,7 @@ internal abstract class KeyExchangeDiffieHellmanGroupShaBase : KeyExchangeDiffie public abstract BigInteger GroupPrime { get; } /// - /// Calculates key exchange hash value. - /// - /// - /// Key exchange hash. - /// - protected override byte[] CalculateHash() - { - var keyExchangeHashData = new KeyExchangeHashData - { - ClientVersion = Session.ClientVersion, - ServerVersion = Session.ServerVersion, - ClientPayload = _clientPayload, - ServerPayload = _serverPayload, - HostKey = _hostKey, - ClientExchangeValue = _clientExchangeValue, - ServerExchangeValue = _serverExchangeValue, - SharedKey = SharedKey, - }; - - return Hash(keyExchangeHashData.GetBytes()); - } - - /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -67,16 +44,39 @@ public override void Finish() Session.KeyExchangeDhReplyMessageReceived -= Session_KeyExchangeDhReplyMessageReceived; } + /// + /// Calculates key exchange hash value. + /// + /// + /// Key exchange hash. + /// + protected override byte[] CalculateHash() + { + var keyExchangeHashData = new KeyExchangeHashData + { + ClientVersion = Session.ClientVersion, + ServerVersion = Session.ServerVersion, + ClientPayload = _clientPayload, + ServerPayload = _serverPayload, + HostKey = _hostKey, + ClientExchangeValue = _clientExchangeValue, + ServerExchangeValue = _serverExchangeValue, + SharedKey = SharedKey, + }; + + return Hash(keyExchangeHashData.GetBytes()); + } + private void Session_KeyExchangeDhReplyMessageReceived(object sender, MessageEventArgs e) { var message = e.Message; - // Unregister message once received + // Unregister message once received Session.UnRegisterMessage("SSH_MSG_KEXDH_REPLY"); HandleServerDhReply(message.HostKey, message.F, message.Signature); - // When SSH_MSG_KEXDH_REPLY received key exchange is completed + // When SSH_MSG_KEXDH_REPLY received key exchange is completed Finish(); } } diff --git a/src/Renci.SshNet/Security/KeyExchangeEC.cs b/src/Renci.SshNet/Security/KeyExchangeEC.cs index 79cdf5be7..864f55d2f 100644 --- a/src/Renci.SshNet/Security/KeyExchangeEC.cs +++ b/src/Renci.SshNet/Security/KeyExchangeEC.cs @@ -1,6 +1,7 @@ using System.Text; -using Renci.SshNet.Messages.Transport; + using Renci.SshNet.Common; +using Renci.SshNet.Messages.Transport; namespace Renci.SshNet.Security { @@ -87,11 +88,12 @@ protected override bool ValidateExchangeHash() { return key.VerifySignature(exchangeHash, _signature); } + return false; } /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -103,4 +105,4 @@ public override void Start(Session session, KeyExchangeInitMessage message) _clientPayload = Session.ClientInitMessage.GetBytes(); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs index b7a318bb9..18443fe73 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECCurve25519.cs @@ -6,7 +6,7 @@ namespace Renci.SshNet.Security { - internal class KeyExchangeECCurve25519 : KeyExchangeEC + internal sealed class KeyExchangeECCurve25519 : KeyExchangeEC { private byte[] _privateKey; @@ -30,7 +30,7 @@ protected override int HashSize } /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -68,7 +68,7 @@ public override void Finish() /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { @@ -82,12 +82,12 @@ private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageE { var message = e.Message; - // Unregister message once received + // Unregister message once received Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY"); HandleServerEcdhReply(message.KS, message.QS, message.Signature); - // When SSH_MSG_KEXDH_REPLY received key exchange is completed + // When SSH_MSG_KEXDH_REPLY received key exchange is completed Finish(); } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH.cs b/src/Renci.SshNet/Security/KeyExchangeECDH.cs index f87a5c7e4..c3fc7bfe4 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH.cs @@ -2,12 +2,12 @@ using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; +using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; +using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Agreement; using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Generators; using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Parameters; -using Renci.SshNet.Security.Org.BouncyCastle.Security; using Renci.SshNet.Security.Org.BouncyCastle.Math.EC; -using Renci.SshNet.Security.Org.BouncyCastle.Asn1.X9; -using Renci.SshNet.Security.Org.BouncyCastle.Crypto.Agreement; +using Renci.SshNet.Security.Org.BouncyCastle.Security; namespace Renci.SshNet.Security { @@ -21,11 +21,11 @@ internal abstract class KeyExchangeECDH : KeyExchangeEC /// protected abstract X9ECParameters CurveParameter { get; } - protected ECDHCBasicAgreement KeyAgreement; - protected ECDomainParameters DomainParameters; + private ECDHCBasicAgreement _keyAgreement; + private ECDomainParameters _domainParameters; /// - /// Starts key exchange algorithm + /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. @@ -37,18 +37,18 @@ public override void Start(Session session, KeyExchangeInitMessage message) Session.KeyExchangeEcdhReplyMessageReceived += Session_KeyExchangeEcdhReplyMessageReceived; - DomainParameters = new ECDomainParameters(CurveParameter.Curve, + _domainParameters = new ECDomainParameters(CurveParameter.Curve, CurveParameter.G, CurveParameter.N, CurveParameter.H, CurveParameter.GetSeed()); var g = new ECKeyPairGenerator(); - g.Init(new ECKeyGenerationParameters(DomainParameters, new SecureRandom())); + g.Init(new ECKeyGenerationParameters(_domainParameters, new SecureRandom())); var aKeyPair = g.GenerateKeyPair(); - KeyAgreement = new ECDHCBasicAgreement(); - KeyAgreement.Init(aKeyPair.Private); + _keyAgreement = new ECDHCBasicAgreement(); + _keyAgreement.Init(aKeyPair.Private); _clientExchangeValue = ((ECPublicKeyParameters)aKeyPair.Public).Q.GetEncoded(); SendMessage(new KeyExchangeEcdhInitMessage(_clientExchangeValue)); @@ -68,12 +68,12 @@ private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageE { var message = e.Message; - // Unregister message once received + // Unregister message once received Session.UnRegisterMessage("SSH_MSG_KEX_ECDH_REPLY"); HandleServerEcdhReply(message.KS, message.QS, message.Signature); - // When SSH_MSG_KEXDH_REPLY received key exchange is completed + // When SSH_MSG_KEXDH_REPLY received key exchange is completed Finish(); } @@ -95,11 +95,11 @@ private void HandleServerEcdhReply(byte[] hostKey, byte[] serverExchangeValue, b var y = new byte[cordSize]; Buffer.BlockCopy(serverExchangeValue, cordSize + 1, y, 0, y.Length); - var c = (FpCurve)DomainParameters.Curve; + var c = (FpCurve)_domainParameters.Curve; var q = c.CreatePoint(new Org.BouncyCastle.Math.BigInteger(1, x), new Org.BouncyCastle.Math.BigInteger(1, y)); - var publicKey = new ECPublicKeyParameters("ECDH", q, DomainParameters); + var publicKey = new ECPublicKeyParameters("ECDH", q, _domainParameters); - var k1 = KeyAgreement.CalculateAgreement(publicKey); + var k1 = _keyAgreement.CalculateAgreement(publicKey); SharedKey = k1.ToByteArray().ToBigInteger2().ToByteArray().Reverse(); } } diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH256.cs b/src/Renci.SshNet/Security/KeyExchangeECDH256.cs index 8f14d9bd4..b09652de8 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH256.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH256.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Security { - internal class KeyExchangeECDH256 : KeyExchangeECDH + internal sealed class KeyExchangeECDH256 : KeyExchangeECDH { /// /// Gets algorithm name. @@ -41,7 +41,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { @@ -51,4 +51,4 @@ protected override byte[] Hash(byte[] hashData) } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH384.cs b/src/Renci.SshNet/Security/KeyExchangeECDH384.cs index bbd7ced51..cba304305 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH384.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH384.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Security { - internal class KeyExchangeECDH384 : KeyExchangeECDH + internal sealed class KeyExchangeECDH384 : KeyExchangeECDH { /// /// Gets algorithm name. @@ -41,7 +41,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { diff --git a/src/Renci.SshNet/Security/KeyExchangeECDH521.cs b/src/Renci.SshNet/Security/KeyExchangeECDH521.cs index 920089c02..ce5b35515 100644 --- a/src/Renci.SshNet/Security/KeyExchangeECDH521.cs +++ b/src/Renci.SshNet/Security/KeyExchangeECDH521.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Security { - internal class KeyExchangeECDH521 : KeyExchangeECDH + internal sealed class KeyExchangeECDH521 : KeyExchangeECDH { /// /// Gets algorithm name. @@ -41,7 +41,7 @@ protected override int HashSize /// /// The hash data. /// - /// Hashed bytes + /// The hash of the data. /// protected override byte[] Hash(byte[] hashData) { @@ -51,4 +51,4 @@ protected override byte[] Hash(byte[] hashData) } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Security/KeyExchangeHash.cs b/src/Renci.SshNet/Security/KeyExchangeHash.cs index e33cb14cc..f91946627 100644 --- a/src/Renci.SshNet/Security/KeyExchangeHash.cs +++ b/src/Renci.SshNet/Security/KeyExchangeHash.cs @@ -1,9 +1,10 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Security { - internal class KeyExchangeHashData : SshData + internal sealed class KeyExchangeHashData : SshData { private byte[] _serverVersion; private byte[] _clientVersion; diff --git a/src/Renci.SshNet/Security/KeyHostAlgorithm.cs b/src/Renci.SshNet/Security/KeyHostAlgorithm.cs index 11717197b..aad8e20c1 100644 --- a/src/Renci.SshNet/Security/KeyHostAlgorithm.cs +++ b/src/Renci.SshNet/Security/KeyHostAlgorithm.cs @@ -37,7 +37,7 @@ public KeyHostAlgorithm(string name, Key key) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// Host key name. /// Host key. @@ -80,7 +80,7 @@ public override bool VerifySignature(byte[] data, byte[] signature) return Key.VerifySignature(data, signatureData.Signature); } - private class SshKeyData : SshData + private sealed class SshKeyData : SshData { private byte[] _name; private List _keys; @@ -90,21 +90,26 @@ public BigInteger[] Keys get { var keys = new BigInteger[_keys.Count]; + for (var i = 0; i < _keys.Count; i++) { var key = _keys[i]; keys[i] = key.ToBigInteger2(); } + return keys; } private set { _keys = new List(value.Length); + foreach (var key in value) { var keyData = key.ToByteArray().Reverse(); if (Name == "ssh-ed25519") + { keyData = keyData.TrimLeadingZeros().Pad(Ed25519.PublicKeySizeInBytes); + } _keys.Add(keyData); } @@ -165,7 +170,7 @@ protected override void SaveData() } } - private class SignatureKeyData : SshData + private sealed class SignatureKeyData : SshData { /// /// Gets or sets the name of the algorithm as UTF-8 encoded byte array. @@ -176,7 +181,7 @@ private class SignatureKeyData : SshData private byte[] AlgorithmName { get; set; } /// - /// Gets or sets the signature. + /// Gets the signature. /// /// /// The signature. diff --git a/src/Renci.SshNet/ServiceFactory.cs b/src/Renci.SshNet/ServiceFactory.cs index f04e6116d..42e541f0b 100644 --- a/src/Renci.SshNet/ServiceFactory.cs +++ b/src/Renci.SshNet/ServiceFactory.cs @@ -1,27 +1,28 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; using System.Text; + +using Renci.SshNet.Abstractions; using Renci.SshNet.Common; +using Renci.SshNet.Connection; using Renci.SshNet.Messages.Transport; using Renci.SshNet.Security; using Renci.SshNet.Sftp; -using Renci.SshNet.Abstractions; -using Renci.SshNet.Connection; -using System.Net.Sockets; namespace Renci.SshNet { /// /// Basic factory for creating new services. /// - internal partial class ServiceFactory : IServiceFactory + internal sealed partial class ServiceFactory : IServiceFactory { /// /// Defines the number of times an authentication attempt with any given /// can result in before it is disregarded. /// - private static int PartialSuccessLimit = 5; + private static readonly int PartialSuccessLimit = 5; /// /// Creates a . @@ -92,9 +93,14 @@ public PipeStream CreatePipeStream() public IKeyExchange CreateKeyExchange(IDictionary clientAlgorithms, string[] serverAlgorithms) { if (clientAlgorithms == null) - throw new ArgumentNullException("clientAlgorithms"); + { + throw new ArgumentNullException(nameof(clientAlgorithms)); + } + if (serverAlgorithms == null) - throw new ArgumentNullException("serverAlgorithms"); + { + throw new ArgumentNullException(nameof(serverAlgorithms)); + } // find an algorithm that is supported by both client and server var keyExchangeAlgorithmType = (from c in clientAlgorithms @@ -157,7 +163,7 @@ public ISftpResponseFactory CreateSftpResponseFactory() /// The TERM environment variable. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. /// The terminal mode values. /// The size of the buffer. @@ -210,9 +216,14 @@ public IRemotePathTransformation CreateRemotePathDoubleQuoteTransformation() public IConnector CreateConnector(IConnectionInfo connectionInfo, ISocketFactory socketFactory) { if (connectionInfo == null) - throw new ArgumentNullException("connectionInfo"); + { + throw new ArgumentNullException(nameof(connectionInfo)); + } + if (socketFactory == null) - throw new ArgumentNullException("socketFactory"); + { + throw new ArgumentNullException(nameof(socketFactory)); + } switch (connectionInfo.ProxyType) { diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs index 13764e386..17dd51256 100644 --- a/src/Renci.SshNet/Session.cs +++ b/src/Renci.SshNet/Session.cs @@ -1,8 +1,13 @@ using System; +using System.Globalization; +using System.Linq; using System.Net.Sockets; using System.Security.Cryptography; using System.Text; using System.Threading; +using System.Threading.Tasks; + +using Renci.SshNet.Abstractions; using Renci.SshNet.Channels; using Renci.SshNet.Common; using Renci.SshNet.Compression; @@ -12,11 +17,7 @@ using Renci.SshNet.Messages.Connection; using Renci.SshNet.Messages.Transport; using Renci.SshNet.Security; -using System.Globalization; -using System.Linq; -using Renci.SshNet.Abstractions; using Renci.SshNet.Security.Cryptography; -using System.Threading.Tasks; namespace Renci.SshNet { @@ -28,21 +29,13 @@ public class Session : ISession internal const byte CarriageReturn = 0x0d; internal const byte LineFeed = 0x0a; - /// - /// Specifies an infinite waiting period. - /// - /// - /// The value of this field is -1 millisecond. - /// - internal static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, -1); - /// /// Specifies an infinite waiting period. /// /// /// The value of this field is -1. /// - internal static readonly int Infinite = -1; + internal const int Infinite = -1; /// /// Specifies maximum packet size defined by the protocol. @@ -78,50 +71,90 @@ public class Session : ISession /// We currently do not enforce this limit. /// /// - private const int LocalChannelDataPacketSize = 1024*64; + private const int LocalChannelDataPacketSize = 1024 * 64; + + /// + /// Specifies an infinite waiting period. + /// + /// + /// The value of this field is -1 millisecond. + /// + internal static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, -1); /// /// Controls how many authentication attempts can take place at the same time. /// /// - /// Some server may restrict number to prevent authentication attacks + /// Some server may restrict number to prevent authentication attacks. /// private static readonly SemaphoreLight AuthenticationConnection = new SemaphoreLight(3); /// - /// Holds metada about session messages + /// Holds the factory to use for creating new services. + /// + private readonly IServiceFactory _serviceFactory; + private readonly ISocketFactory _socketFactory; + + /// + /// Holds an object that is used to ensure only a single thread can read from + /// at any given time. + /// + private readonly object _socketReadLock = new object(); + + /// + /// Holds an object that is used to ensure only a single thread can write to + /// at any given time. + /// + /// + /// This is also used to ensure that is + /// incremented atomatically. + /// + private readonly object _socketWriteLock = new object(); + + /// + /// Holds an object that is used to ensure only a single thread can dispose + /// at any given time. + /// + /// + /// This is also used to ensure that will not be disposed + /// while performing a given operation or set of operations on . + /// + private readonly object _socketDisposeLock = new object(); + + /// + /// Holds metadata about session messages. /// private SshMessageFactory _sshMessageFactory; /// /// Holds a that is signaled when the message listener loop has completed. /// - private EventWaitHandle _messageListenerCompleted; + private ManualResetEvent _messageListenerCompleted; /// - /// Specifies outbound packet number + /// Specifies outbound packet number. /// private volatile uint _outboundPacketSequence; /// - /// Specifies incoming packet number + /// Specifies incoming packet number. /// private uint _inboundPacketSequence; /// - /// WaitHandle to signal that last service request was accepted + /// WaitHandle to signal that last service request was accepted. /// - private EventWaitHandle _serviceAccepted = new AutoResetEvent(false); + private EventWaitHandle _serviceAccepted = new AutoResetEvent(initialState: false); /// /// WaitHandle to signal that exception was thrown by another thread. /// - private EventWaitHandle _exceptionWaitHandle = new ManualResetEvent(false); + private EventWaitHandle _exceptionWaitHandle = new ManualResetEvent(initialState: false); /// /// WaitHandle to signal that key exchange was completed. /// - private EventWaitHandle _keyExchangeCompletedWaitHandle = new ManualResetEvent(false); + private EventWaitHandle _keyExchangeCompletedWaitHandle = new ManualResetEvent(initialState: false); /// /// WaitHandle to signal that key exchange is in progress. @@ -129,17 +162,17 @@ public class Session : ISession private bool _keyExchangeInProgress; /// - /// Exception that need to be thrown by waiting thread + /// Exception that need to be thrown by waiting thread. /// private Exception _exception; /// - /// Specifies whether connection is authenticated + /// Specifies whether connection is authenticated. /// private bool _isAuthenticated; /// - /// Specifies whether user issued Disconnect command or not + /// Specifies whether user issued Disconnect command or not. /// private bool _isDisconnecting; @@ -159,43 +192,11 @@ public class Session : ISession private SemaphoreLight _sessionSemaphore; - /// - /// Holds the factory to use for creating new services. - /// - private readonly IServiceFactory _serviceFactory; - private readonly ISocketFactory _socketFactory; - /// /// Holds connection socket. /// private Socket _socket; - /// - /// Holds an object that is used to ensure only a single thread can read from - /// at any given time. - /// - private readonly object _socketReadLock = new object(); - - /// - /// Holds an object that is used to ensure only a single thread can write to - /// at any given time. - /// - /// - /// This is also used to ensure that is - /// incremented atomatically. - /// - private readonly object _socketWriteLock = new object(); - - /// - /// Holds an object that is used to ensure only a single thread can dispose - /// at any given time. - /// - /// - /// This is also used to ensure that will not be disposed - /// while performing a given operation or set of operations on . - /// - private readonly object _socketDisposeLock = new object(); - /// /// Gets the session semaphore that controls session channels. /// @@ -277,9 +278,14 @@ public bool IsConnected get { if (_disposed || _isDisconnectMessageSent || !_isAuthenticated) + { return false; + } + if (_messageListenerCompleted == null || _messageListenerCompleted.WaitOne(0)) + { return false; + } return IsSocketConnected(); } @@ -315,32 +321,39 @@ public Message ClientInitMessage MacAlgorithmsServerToClient = ConnectionInfo.HmacAlgorithms.Keys.ToArray(), CompressionAlgorithmsClientToServer = ConnectionInfo.CompressionAlgorithms.Keys.ToArray(), CompressionAlgorithmsServerToClient = ConnectionInfo.CompressionAlgorithms.Keys.ToArray(), - LanguagesClientToServer = new[] {string.Empty}, - LanguagesServerToClient = new[] {string.Empty}, + LanguagesClientToServer = new[] { string.Empty }, + LanguagesServerToClient = new[] { string.Empty }, FirstKexPacketFollows = false, Reserved = 0 }; } + return _clientInitMessage; } } /// - /// Gets or sets the server version string. + /// Gets the server version string. /// - /// The server version. + /// + /// The server version. + /// public string ServerVersion { get; private set; } /// - /// Gets or sets the client version string. + /// Gets the client version string. /// - /// The client version. + /// + /// The client version. + /// public string ClientVersion { get; private set; } /// - /// Gets or sets the connection info. + /// Gets the connection info. /// - /// The connection info. + /// + /// The connection info. + /// public ConnectionInfo ConnectionInfo { get; private set; } /// @@ -388,8 +401,6 @@ public Message ClientInitMessage /// internal event EventHandler> KeyExchangeDhGroupExchangeReplyReceived; - #region Message events - /// /// Occurs when message received /// @@ -525,8 +536,6 @@ public Message ClientInitMessage /// public event EventHandler> ChannelFailureReceived; - #endregion - /// /// Initializes a new instance of the class. /// @@ -539,17 +548,25 @@ public Message ClientInitMessage internal Session(ConnectionInfo connectionInfo, IServiceFactory serviceFactory, ISocketFactory socketFactory) { if (connectionInfo == null) - throw new ArgumentNullException("connectionInfo"); + { + throw new ArgumentNullException(nameof(connectionInfo)); + } + if (serviceFactory == null) - throw new ArgumentNullException("serviceFactory"); + { + throw new ArgumentNullException(nameof(serviceFactory)); + } + if (socketFactory == null) - throw new ArgumentNullException("socketFactory"); + { + throw new ArgumentNullException(nameof(socketFactory)); + } ClientVersion = "SSH-2.0-Renci.SshNet.SshClient.0.0.1"; ConnectionInfo = connectionInfo; _serviceFactory = serviceFactory; _socketFactory = socketFactory; - _messageListenerCompleted = new ManualResetEvent(true); + _messageListenerCompleted = new ManualResetEvent(initialState: true); } /// @@ -562,20 +579,26 @@ internal Session(ConnectionInfo connectionInfo, IServiceFactory serviceFactory, public void Connect() { if (IsConnected) + { return; + } try { AuthenticationConnection.Wait(); if (IsConnected) + { return; + } lock (this) { // If connected don't connect again if (IsConnected) + { return; + } // Reset connection specific information Reset(); @@ -614,7 +637,7 @@ public void Connect() RegisterMessage("SSH_MSG_USERAUTH_BANNER"); // Mark the message listener threads as started - _messageListenerCompleted.Reset(); + _ = _messageListenerCompleted.Reset(); // Start incoming request listener // ToDo: Make message pump async, to not consume a thread for every session @@ -665,7 +688,7 @@ public void Connect() } finally { - AuthenticationConnection.Release(); + _ = AuthenticationConnection.Release(); } } @@ -685,7 +708,9 @@ public async Task ConnectAsync(CancellationToken cancellationToken) { // If connected don't connect again if (IsConnected) + { return; + } // Reset connection specific information Reset(); @@ -724,7 +749,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken) RegisterMessage("SSH_MSG_USERAUTH_BANNER"); // Mark the message listener threads as started - _messageListenerCompleted.Reset(); + _ = _messageListenerCompleted.Reset(); // Start incoming request listener // ToDo: Make message pump async, to not consume a thread for every session @@ -792,7 +817,7 @@ public void Disconnect() // has completed if (_messageListenerCompleted != null) { - _messageListenerCompleted.WaitOne(); + _ = _messageListenerCompleted.WaitOne(); } } @@ -879,8 +904,7 @@ internal void WaitOnHandle(WaitHandle waitHandle) /// WaitResult ISession.TryWait(WaitHandle waitHandle, TimeSpan timeout) { - Exception exception; - return TryWait(waitHandle, timeout, out exception); + return TryWait(waitHandle, timeout, out _); } /// @@ -911,7 +935,9 @@ WaitResult ISession.TryWait(WaitHandle waitHandle, TimeSpan timeout, out Excepti private WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exception exception) { if (waitHandle == null) - throw new ArgumentNullException("waitHandle"); + { + throw new ArgumentNullException(nameof(waitHandle)); + } var waitHandles = new[] { @@ -928,6 +954,7 @@ private WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exceptio exception = null; return WaitResult.Disconnected; } + exception = _exception; return WaitResult.Failed; case 1: @@ -956,7 +983,9 @@ private WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exceptio internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout) { if (waitHandle == null) - throw new ArgumentNullException("waitHandle"); + { + throw new ArgumentNullException(nameof(waitHandle)); + } var waitHandles = new[] { @@ -982,6 +1011,7 @@ internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout) { throw new SshOperationTimeoutException("Session operation has timed out"); } + break; } } @@ -996,11 +1026,13 @@ internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout) internal void SendMessage(Message message) { if (!_socket.CanWrite()) + { throw new SshConnectionException("Client not connected."); + } - if (_keyExchangeInProgress && !(message is IKeyExchangedAllowed)) + if (_keyExchangeInProgress && message is not IKeyExchangedAllowed) { - // Wait for key exchange to be completed + // Wait for key exchange to be completed WaitOnHandle(_keyExchangeCompletedWaitHandle); } @@ -1020,14 +1052,15 @@ internal void SendMessage(Message message) { // write outbound packet sequence to start of packet data Pack.UInt32ToBigEndian(_outboundPacketSequence, packetData); - // calculate packet hash + + // calculate packet hash hash = _clientMac.ComputeHash(packetData); } // Encrypt packet data if (_clientCipher != null) { - packetData = _clientCipher.Encrypt(packetData, packetDataOffset, (packetData.Length - packetDataOffset)); + packetData = _clientCipher.Encrypt(packetData, packetDataOffset, packetData.Length - packetDataOffset); packetDataOffset = 0; } @@ -1052,7 +1085,7 @@ internal void SendMessage(Message message) // increment the packet sequence number only after we're sure the packet has // been sent; even though it's only used for the MAC, it needs to be incremented // for each package sent. - // + // // the server will use it to verify the data integrity, and as such the order in // which messages are sent must follow the outbound packet sequence number _outboundPacketSequence++; @@ -1081,7 +1114,9 @@ private void SendPacket(byte[] packet, int offset, int length) lock (_socketDisposeLock) { if (!_socket.IsConnected()) + { throw new SshConnectionException("Client not connected."); + } SocketAbstraction.Send(_socket, packet, offset, length); } @@ -1131,8 +1166,10 @@ private Message ReceiveMessage(Socket socket) { // the length of the packet sequence field in bytes const int inboundPacketSequenceLength = 4; + // The length of the "packet length" field in bytes const int packetLengthFieldLength = 4; + // The length of the "padding length" field in bytes const int paddingLengthFieldLength = 1; @@ -1149,7 +1186,7 @@ private Message ReceiveMessage(Socket socket) // Socket.Available lock (_socketReadLock) { - // Read first block - which starts with the packet length + // Read first block - which starts with the packet length var firstBlock = new byte[blockSize]; if (TrySocketRead(socket, firstBlock, 0, blockSize) == 0) { @@ -1166,9 +1203,10 @@ private Message ReceiveMessage(Socket socket) // Test packet minimum and maximum boundaries if (packetLength < Math.Max((byte) 16, blockSize) - 4 || packetLength > MaximumSshPacketSize - 4) - throw new SshConnectionException( - string.Format(CultureInfo.CurrentCulture, "Bad packet length: {0}.", packetLength), - DisconnectReason.ProtocolError); + { + throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length: {0}.", packetLength), + DisconnectReason.ProtocolError); + } // Determine the number of bytes left to read; We've already read "blockSize" bytes, but the // "packet length" field itself - which is 4 bytes - is not included in the length of the packet @@ -1176,12 +1214,12 @@ private Message ReceiveMessage(Socket socket) // Construct buffer for holding the payload and the inbound packet sequence as we need both in order // to generate the hash. - // + // // The total length of the "data" buffer is an addition of: // - inboundPacketSequenceLength (4 bytes) // - packetLength // - serverMacLength - // + // // We include the inbound packet sequence to allow us to have the the full SSH packet in a single // byte[] for the purpose of calculating the client hash. Room for the server MAC is foreseen // to read the packet including server MAC in a single pass (except for the initial block). @@ -1232,6 +1270,7 @@ private Message ReceiveMessage(Socket socket) // data now only contains the decompressed payload, and as such the offset is reset to zero messagePayloadOffset = 0; + // the length of the payload is now the complete decompressed content messagePayloadLength = data.Length; } @@ -1246,14 +1285,12 @@ private void TrySendDisconnect(DisconnectReason reasonCode, string message) var disconnectMessage = new DisconnectMessage(reasonCode, message); // send the disconnect message, but ignore the outcome - TrySendMessage(disconnectMessage); + _ = TrySendMessage(disconnectMessage); // mark disconnect message sent regardless of whether the send sctually succeeded _isDisconnectMessageSent = true; } - #region Handle received message events - /// /// Called when received. /// @@ -1268,15 +1305,11 @@ internal void OnDisconnectReceived(DisconnectMessage message) _isDisconnecting = true; _exception = new SshConnectionException(string.Format(CultureInfo.InvariantCulture, "The connection was closed by the server: {0} ({1}).", message.Description, message.ReasonCode), message.ReasonCode); - _exceptionWaitHandle.Set(); + _ = _exceptionWaitHandle.Set(); - var disconnectReceived = DisconnectReceived; - if (disconnectReceived != null) - disconnectReceived(this, new MessageEventArgs(message)); + DisconnectReceived?.Invoke(this, new MessageEventArgs(message)); - var disconnected = Disconnected; - if (disconnected != null) - disconnected(this, new EventArgs()); + Disconnected?.Invoke(this, EventArgs.Empty); // disconnect socket, and dispose it SocketDisconnectAndDispose(); @@ -1288,9 +1321,7 @@ internal void OnDisconnectReceived(DisconnectMessage message) /// message. internal void OnIgnoreReceived(IgnoreMessage message) { - var handlers = IgnoreReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + IgnoreReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1299,9 +1330,7 @@ internal void OnIgnoreReceived(IgnoreMessage message) /// message. internal void OnUnimplementedReceived(UnimplementedMessage message) { - var handlers = UnimplementedReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UnimplementedReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1310,9 +1339,7 @@ internal void OnUnimplementedReceived(UnimplementedMessage message) /// message. internal void OnDebugReceived(DebugMessage message) { - var handlers = DebugReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + DebugReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1321,9 +1348,7 @@ internal void OnDebugReceived(DebugMessage message) /// message. internal void OnServiceRequestReceived(ServiceRequestMessage message) { - var handlers = ServiceRequestReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ServiceRequestReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1332,25 +1357,19 @@ internal void OnServiceRequestReceived(ServiceRequestMessage message) /// message. internal void OnServiceAcceptReceived(ServiceAcceptMessage message) { - var handlers = ServiceAcceptReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ServiceAcceptReceived?.Invoke(this, new MessageEventArgs(message)); - _serviceAccepted.Set(); + _ = _serviceAccepted.Set(); } internal void OnKeyExchangeDhGroupExchangeGroupReceived(KeyExchangeDhGroupExchangeGroup message) { - var handlers = KeyExchangeDhGroupExchangeGroupReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + KeyExchangeDhGroupExchangeGroupReceived?.Invoke(this, new MessageEventArgs(message)); } internal void OnKeyExchangeDhGroupExchangeReplyReceived(KeyExchangeDhGroupExchangeReply message) { - var handlers = KeyExchangeDhGroupExchangeReplyReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + KeyExchangeDhGroupExchangeReplyReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1361,7 +1380,7 @@ internal void OnKeyExchangeInitReceived(KeyExchangeInitMessage message) { _keyExchangeInProgress = true; - _keyExchangeCompletedWaitHandle.Reset(); + _ = _keyExchangeCompletedWaitHandle.Reset(); // Disable messages that are not key exchange related _sshMessageFactory.DisableNonKeyExchangeMessages(); @@ -1373,26 +1392,20 @@ internal void OnKeyExchangeInitReceived(KeyExchangeInitMessage message) _keyExchange.HostKeyReceived += KeyExchange_HostKeyReceived; - // Start the algorithm implementation + // Start the algorithm implementation _keyExchange.Start(this, message); - var keyExchangeInitReceived = KeyExchangeInitReceived; - if (keyExchangeInitReceived != null) - keyExchangeInitReceived(this, new MessageEventArgs(message)); + KeyExchangeInitReceived?.Invoke(this, new MessageEventArgs(message)); } internal void OnKeyExchangeDhReplyMessageReceived(KeyExchangeDhReplyMessage message) { - var handlers = KeyExchangeDhReplyMessageReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + KeyExchangeDhReplyMessageReceived?.Invoke(this, new MessageEventArgs(message)); } internal void OnKeyExchangeEcdhReplyMessageReceived(KeyExchangeEcdhReplyMessage message) { - var handlers = KeyExchangeEcdhReplyMessageReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + KeyExchangeEcdhReplyMessageReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1401,13 +1414,10 @@ internal void OnKeyExchangeEcdhReplyMessageReceived(KeyExchangeEcdhReplyMessage /// message. internal void OnNewKeysReceived(NewKeysMessage message) { - // Update sessionId - if (SessionId == null) - { - SessionId = _keyExchange.ExchangeHash; - } + // Update sessionId + SessionId ??= _keyExchange.ExchangeHash; - // Dispose of old ciphers and hash algorithms + // Dispose of old ciphers and hash algorithms if (_serverMac != null) { _serverMac.Dispose(); @@ -1420,7 +1430,7 @@ internal void OnNewKeysReceived(NewKeysMessage message) _clientMac = null; } - // Update negotiated algorithms + // Update negotiated algorithms _serverCipher = _keyExchange.CreateServerCipher(); _clientCipher = _keyExchange.CreateClientCipher(); _serverMac = _keyExchange.CreateServerHash(); @@ -1428,7 +1438,7 @@ internal void OnNewKeysReceived(NewKeysMessage message) _clientCompression = _keyExchange.CreateCompressor(); _serverDecompression = _keyExchange.CreateDecompressor(); - // Dispose of old KeyExchange object as it is no longer needed. + // Dispose of old KeyExchange object as it is no longer needed. if (_keyExchange != null) { _keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived; @@ -1439,12 +1449,10 @@ internal void OnNewKeysReceived(NewKeysMessage message) // Enable activated messages that are not key exchange related _sshMessageFactory.EnableActivatedMessages(); - var newKeysReceived = NewKeysReceived; - if (newKeysReceived != null) - newKeysReceived(this, new MessageEventArgs(message)); + NewKeysReceived?.Invoke(this, new MessageEventArgs(message)); - // Signal that key exchange completed - _keyExchangeCompletedWaitHandle.Set(); + // Signal that key exchange completed + _ = _keyExchangeCompletedWaitHandle.Set(); _keyExchangeInProgress = false; } @@ -1463,9 +1471,7 @@ void ISession.OnDisconnecting() /// message. internal void OnUserAuthenticationRequestReceived(RequestMessage message) { - var handlers = UserAuthenticationRequestReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationRequestReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1474,9 +1480,7 @@ internal void OnUserAuthenticationRequestReceived(RequestMessage message) /// message. internal void OnUserAuthenticationFailureReceived(FailureMessage message) { - var handlers = UserAuthenticationFailureReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationFailureReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1485,9 +1489,7 @@ internal void OnUserAuthenticationFailureReceived(FailureMessage message) /// message. internal void OnUserAuthenticationSuccessReceived(SuccessMessage message) { - var handlers = UserAuthenticationSuccessReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationSuccessReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1496,35 +1498,26 @@ internal void OnUserAuthenticationSuccessReceived(SuccessMessage message) /// message. internal void OnUserAuthenticationBannerReceived(BannerMessage message) { - var handlers = UserAuthenticationBannerReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationBannerReceived?.Invoke(this, new MessageEventArgs(message)); } - /// /// Called when message received. /// /// message. internal void OnUserAuthenticationInformationRequestReceived(InformationRequestMessage message) { - var handlers = UserAuthenticationInformationRequestReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationInformationRequestReceived?.Invoke(this, new MessageEventArgs(message)); } internal void OnUserAuthenticationPasswordChangeRequiredReceived(PasswordChangeRequiredMessage message) { - var handlers = UserAuthenticationPasswordChangeRequiredReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationPasswordChangeRequiredReceived?.Invoke(this, new MessageEventArgs(message)); } internal void OnUserAuthenticationPublicKeyReceived(PublicKeyMessage message) { - var handlers = UserAuthenticationPublicKeyReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + UserAuthenticationPublicKeyReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1533,9 +1526,7 @@ internal void OnUserAuthenticationPublicKeyReceived(PublicKeyMessage message) /// message. internal void OnGlobalRequestReceived(GlobalRequestMessage message) { - var handlers = GlobalRequestReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + GlobalRequestReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1544,9 +1535,7 @@ internal void OnGlobalRequestReceived(GlobalRequestMessage message) /// message. internal void OnRequestSuccessReceived(RequestSuccessMessage message) { - var handlers = RequestSuccessReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + RequestSuccessReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1555,9 +1544,7 @@ internal void OnRequestSuccessReceived(RequestSuccessMessage message) /// message. internal void OnRequestFailureReceived(RequestFailureMessage message) { - var handlers = RequestFailureReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + RequestFailureReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1566,9 +1553,7 @@ internal void OnRequestFailureReceived(RequestFailureMessage message) /// message. internal void OnChannelOpenReceived(ChannelOpenMessage message) { - var handlers = ChannelOpenReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelOpenReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1577,9 +1562,7 @@ internal void OnChannelOpenReceived(ChannelOpenMessage message) /// message. internal void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage message) { - var handlers = ChannelOpenConfirmationReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelOpenConfirmationReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1588,9 +1571,7 @@ internal void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage m /// message. internal void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message) { - var handlers = ChannelOpenFailureReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelOpenFailureReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1599,9 +1580,7 @@ internal void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message) /// message. internal void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message) { - var handlers = ChannelWindowAdjustReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelWindowAdjustReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1610,9 +1589,7 @@ internal void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message) /// message. internal void OnChannelDataReceived(ChannelDataMessage message) { - var handlers = ChannelDataReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelDataReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1621,9 +1598,7 @@ internal void OnChannelDataReceived(ChannelDataMessage message) /// message. internal void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message) { - var handlers = ChannelExtendedDataReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelExtendedDataReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1632,9 +1607,7 @@ internal void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message) /// message. internal void OnChannelEofReceived(ChannelEofMessage message) { - var handlers = ChannelEofReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelEofReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1643,9 +1616,7 @@ internal void OnChannelEofReceived(ChannelEofMessage message) /// message. internal void OnChannelCloseReceived(ChannelCloseMessage message) { - var handlers = ChannelCloseReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelCloseReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1654,9 +1625,7 @@ internal void OnChannelCloseReceived(ChannelCloseMessage message) /// message. internal void OnChannelRequestReceived(ChannelRequestMessage message) { - var handlers = ChannelRequestReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelRequestReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1665,9 +1634,7 @@ internal void OnChannelRequestReceived(ChannelRequestMessage message) /// message. internal void OnChannelSuccessReceived(ChannelSuccessMessage message) { - var handlers = ChannelSuccessReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelSuccessReceived?.Invoke(this, new MessageEventArgs(message)); } /// @@ -1676,22 +1643,14 @@ internal void OnChannelSuccessReceived(ChannelSuccessMessage message) /// message. internal void OnChannelFailureReceived(ChannelFailureMessage message) { - var handlers = ChannelFailureReceived; - if (handlers != null) - handlers(this, new MessageEventArgs(message)); + ChannelFailureReceived?.Invoke(this, new MessageEventArgs(message)); } - #endregion - private void KeyExchange_HostKeyReceived(object sender, HostKeyEventArgs e) { - var handlers = HostKeyReceived; - if (handlers != null) - handlers(this, e); + HostKeyReceived?.Invoke(this, e); } - #region Message loading functions - /// /// Registers SSH message with the session. /// @@ -1741,7 +1700,7 @@ private static string ToHex(byte[] bytes, int offset) for (var i = offset; i < byteCount; i++) { var b = bytes[i]; - builder.Append(b.ToString("X2")); + _ = builder.Append(b.ToString("X2")); } return builder.ToString(); @@ -1750,13 +1709,13 @@ private static string ToHex(byte[] bytes, int offset) internal static string ToHex(byte[] bytes) { if (bytes == null) + { return null; + } return ToHex(bytes, 0); } - #endregion - /// /// Gets a value indicating whether the socket is connected. /// @@ -1933,7 +1892,7 @@ private void MessageListener() finally { // signal that the message listener thread has stopped - _messageListenerCompleted.Set(); + _ = _messageListenerCompleted.Set(); } } @@ -1949,25 +1908,26 @@ private void RaiseError(Exception exp) if (_isDisconnecting) { - // a connection exception which is raised while isDisconnecting is normal and - // should be ignored + // a connection exception which is raised while isDisconnecting is normal and + // should be ignored if (connectionException != null) + { return; + } // any timeout while disconnecting can be caused by loss of connectivity // altogether and should be ignored - var socketException = exp as SocketException; - if (socketException != null && socketException.SocketErrorCode == SocketError.TimedOut) + if (exp is SocketException socketException && socketException.SocketErrorCode == SocketError.TimedOut) + { return; + } } // "save" exception and set exception wait handle to ensure any waits are interrupted _exception = exp; - _exceptionWaitHandle.Set(); + _ = _exceptionWaitHandle.Set(); - var errorOccured = ErrorOccured; - if (errorOccured != null) - errorOccured(this, new ExceptionEventArgs(exp)); + ErrorOccured?.Invoke(this, new ExceptionEventArgs(exp)); if (connectionException != null) { @@ -1982,12 +1942,9 @@ private void RaiseError(Exception exp) /// private void Reset() { - if (_exceptionWaitHandle != null) - _exceptionWaitHandle.Reset(); - if (_keyExchangeCompletedWaitHandle != null) - _keyExchangeCompletedWaitHandle.Reset(); - if (_messageListenerCompleted != null) - _messageListenerCompleted.Set(); + _ = _exceptionWaitHandle?.Reset(); + _ = _keyExchangeCompletedWaitHandle?.Reset(); + _ = _messageListenerCompleted?.Set(); SessionId = null; _isDisconnectMessageSent = false; @@ -2003,8 +1960,6 @@ private static SshConnectionException CreateConnectionAbortedByServerException() DisconnectReason.ConnectionLost); } -#region IDisposable implementation - private bool _disposed; /// @@ -2012,18 +1967,20 @@ private static SshConnectionException CreateConnectionAbortedByServerException() /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_disposed) + { return; + } if (disposing) { @@ -2086,20 +2043,15 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~Session() { - Dispose(false); + Dispose(disposing: false); } -#endregion IDisposable implementation - -#region ISession implementation - /// - /// Gets or sets the connection info. + /// Gets the connection info. /// /// The connection info. IConnectionInfo ISession.ConnectionInfo @@ -2181,8 +2133,6 @@ bool ISession.TrySendMessage(Message message) { return TrySendMessage(message); } - -#endregion ISession implementation } /// @@ -2210,4 +2160,4 @@ internal enum WaitResult /// Failed = 4 } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/ISftpFile.cs b/src/Renci.SshNet/Sftp/ISftpFile.cs index 60c4a7a52..fb0d8b224 100644 --- a/src/Renci.SshNet/Sftp/ISftpFile.cs +++ b/src/Renci.SshNet/Sftp/ISftpFile.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp { /// - /// Represents SFTP file information + /// Represents SFTP file information. /// public interface ISftpFile { @@ -13,14 +13,23 @@ public interface ISftpFile SftpFileAttributes Attributes { get; } /// - /// Gets the full path of the directory or file. + /// Gets the full path of the file or directory. /// + /// + /// The full path of the file or directory. + /// string FullName { get; } /// - /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists. - /// Otherwise, the Name property gets the name of the directory. + /// Gets the name of the file or directory. /// + /// + /// The name of the file or directory. + /// + /// + /// For directories, this is the name of the last directory in the hierarchy if a hierarchy exists; + /// otherwise, the name of the directory. + /// string Name { get; } /// @@ -56,7 +65,7 @@ public interface ISftpFile DateTime LastWriteTimeUtc { get; set; } /// - /// Gets or sets the size, in bytes, of the current file. + /// Gets the size, in bytes, of the current file. /// /// /// The size of the current file in bytes. @@ -83,7 +92,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a socket. /// /// - /// true if file represents a socket; otherwise, false. + /// true if file represents a socket; otherwise, false. /// bool IsSocket { get; } @@ -91,7 +100,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a symbolic link. /// /// - /// true if file represents a symbolic link; otherwise, false. + /// true if file represents a symbolic link; otherwise, false. /// bool IsSymbolicLink { get; } @@ -99,7 +108,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a regular file. /// /// - /// true if file represents a regular file; otherwise, false. + /// true if file represents a regular file; otherwise, false. /// bool IsRegularFile { get; } @@ -107,7 +116,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a block device. /// /// - /// true if file represents a block device; otherwise, false. + /// true if file represents a block device; otherwise, false. /// bool IsBlockDevice { get; } @@ -115,7 +124,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a directory. /// /// - /// true if file represents a directory; otherwise, false. + /// true if file represents a directory; otherwise, false. /// bool IsDirectory { get; } @@ -123,7 +132,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a character device. /// /// - /// true if file represents a character device; otherwise, false. + /// true if file represents a character device; otherwise, false. /// bool IsCharacterDevice { get; } @@ -131,7 +140,7 @@ public interface ISftpFile /// Gets a value indicating whether file represents a named pipe. /// /// - /// true if file represents a named pipe; otherwise, false. + /// true if file represents a named pipe; otherwise, false. /// bool IsNamedPipe { get; } @@ -139,7 +148,7 @@ public interface ISftpFile /// Gets or sets a value indicating whether the owner can read from this file. /// /// - /// true if owner can read from this file; otherwise, false. + /// true if owner can read from this file; otherwise, false. /// bool OwnerCanRead { get; set; } @@ -230,4 +239,4 @@ public interface ISftpFile /// void UpdateStatus(); } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/ISftpSession.cs b/src/Renci.SshNet/Sftp/ISftpSession.cs index 8971bd571..39b48e7f1 100644 --- a/src/Renci.SshNet/Sftp/ISftpSession.cs +++ b/src/Renci.SshNet/Sftp/ISftpSession.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; using System.Threading; -using Renci.SshNet.Sftp.Responses; using System.Threading.Tasks; +using Renci.SshNet.Sftp.Responses; + namespace Renci.SshNet.Sftp { internal interface ISftpSession : ISubsystemSession @@ -59,12 +60,12 @@ internal interface ISftpSession : ISubsystemSession /// The path. /// if set to true returns null instead of throwing an exception. /// - /// File attributes + /// File attributes. /// SftpFileAttributes RequestStat(string path, bool nullOnError = false); /// - /// Performs SSH_FXP_STAT request + /// Performs SSH_FXP_STAT request. /// /// The path. /// The delegate that is executed when completes. @@ -121,7 +122,7 @@ internal interface ISftpSession : ISubsystemSession void RequestMkDir(string path); /// - /// Performs SSH_FXP_OPEN request + /// Performs SSH_FXP_OPEN request. /// /// The path. /// The flags. @@ -132,7 +133,7 @@ internal interface ISftpSession : ISubsystemSession Task RequestOpenAsync(string path, Flags flags, CancellationToken cancellationToken); /// - /// Performs SSH_FXP_OPEN request + /// Performs SSH_FXP_OPEN request. /// /// The path. /// The flags. @@ -158,7 +159,7 @@ internal interface ISftpSession : ISubsystemSession byte[] EndOpen(SftpOpenAsyncResult asyncResult); /// - /// Performs SSH_FXP_OPENDIR request + /// Performs SSH_FXP_OPENDIR request. /// /// The path. /// if set to true returns null instead of throwing an exception. @@ -213,7 +214,7 @@ internal interface ISftpSession : ISubsystemSession Task RequestReadAsync(byte[] handle, ulong offset, uint length, CancellationToken cancellationToken); /// - /// Performs SSH_FXP_READDIR request + /// Performs SSH_FXP_READDIR request. /// /// The handle. /// diff --git a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs index 5b5b02ecd..06eeef1e2 100644 --- a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs @@ -42,8 +42,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var extendedReplyResponse = response as SftpExtendedReplyResponse; - if (extendedReplyResponse != null) + if (response is SftpExtendedReplyResponse extendedReplyResponse) { _extendedReplyAction(extendedReplyResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs index de7e06db4..963249d22 100644 --- a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class HardLinkRequest : SftpExtendedRequest + internal sealed class HardLinkRequest : SftpExtendedRequest { private byte[] _oldPath; private byte[] _newPath; @@ -53,4 +53,4 @@ protected override void SaveData() WriteBinaryString(_newPath); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs index d0b530f08..5d996723b 100644 --- a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs @@ -1,10 +1,11 @@ using System; -using Renci.SshNet.Sftp.Responses; using System.Text; +using Renci.SshNet.Sftp.Responses; + namespace Renci.SshNet.Sftp.Requests { - internal class PosixRenameRequest : SftpExtendedRequest + internal sealed class PosixRenameRequest : SftpExtendedRequest { private byte[] _oldPath; private byte[] _newPath; @@ -21,7 +22,7 @@ public string NewPath private set { _newPath = Encoding.GetBytes(value); } } - public Encoding Encoding { get; private set; } + public Encoding Encoding { get; } /// /// Gets the size of the message in bytes. @@ -53,8 +54,9 @@ public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, protected override void SaveData() { base.SaveData(); + WriteBinaryString(_oldPath); WriteBinaryString(_newPath); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs index b1bda3c06..fe4373257 100644 --- a/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs @@ -1,13 +1,14 @@ using System; -using Renci.SshNet.Sftp.Responses; using System.Text; +using Renci.SshNet.Sftp.Responses; + namespace Renci.SshNet.Sftp.Requests { - internal class StatVfsRequest : SftpExtendedRequest + internal sealed class StatVfsRequest : SftpExtendedRequest { - private byte[] _path; private readonly Action _extendedReplyAction; + private byte[] _path; public string Path { @@ -51,8 +52,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var extendedReplyResponse = response as SftpExtendedReplyResponse; - if (extendedReplyResponse != null) + if (response is SftpExtendedReplyResponse extendedReplyResponse) { _extendedReplyAction(extendedReplyResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs index 9414150c0..9c2ccd6ca 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs @@ -1,9 +1,10 @@ using System; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpBlockRequest : SftpRequest + internal sealed class SftpBlockRequest : SftpRequest { public override SftpMessageTypes SftpMessageType { @@ -38,7 +39,7 @@ protected override int BufferCapacity } } - public SftpBlockRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt64 length, UInt32 lockMask, Action statusAction) + public SftpBlockRequest(uint protocolVersion, uint requestId, byte[] handle, ulong offset, ulong length, uint lockMask, Action statusAction) : base(protocolVersion, requestId, statusAction) { Handle = handle; @@ -50,6 +51,7 @@ public SftpBlockRequest(uint protocolVersion, uint requestId, byte[] handle, UIn protected override void LoadData() { base.LoadData(); + Handle = ReadBinary(); Offset = ReadUInt64(); Length = ReadUInt64(); @@ -59,6 +61,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(Handle); Write(Offset); Write(Length); diff --git a/src/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs index dd2dace1a..f17673f95 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpCloseRequest : SftpRequest + internal sealed class SftpCloseRequest : SftpRequest { public override SftpMessageTypes SftpMessageType { diff --git a/src/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs index 5de45c5ae..d24f757b8 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpFSetStatRequest : SftpRequest + internal sealed class SftpFSetStatRequest : SftpRequest { private byte[] _attributesBytes; @@ -20,10 +20,7 @@ private byte[] AttributesBytes { get { - if (_attributesBytes == null) - { - _attributesBytes = Attributes.GetBytes(); - } + _attributesBytes ??= Attributes.GetBytes(); return _attributesBytes; } } @@ -56,6 +53,7 @@ public SftpFSetStatRequest(uint protocolVersion, uint requestId, byte[] handle, protected override void LoadData() { base.LoadData(); + Handle = ReadBinary(); Attributes = ReadAttributes(); } @@ -63,6 +61,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(Handle); Write(AttributesBytes); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs index da71a62ea..6fa4576f6 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs @@ -1,9 +1,10 @@ using System; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpFStatRequest : SftpRequest + internal sealed class SftpFStatRequest : SftpRequest { private readonly Action _attrsAction; @@ -52,8 +53,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var attrsResponse = response as SftpAttrsResponse; - if (attrsResponse != null) + if (response is SftpAttrsResponse attrsResponse) { _attrsAction(attrsResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs index cb95c7c0e..25e21dabf 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs @@ -1,6 +1,6 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpInitRequest : SftpMessage + internal sealed class SftpInitRequest : SftpMessage { public override SftpMessageTypes SftpMessageType { diff --git a/src/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs index 1edb9c695..950ef8f43 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs @@ -4,10 +4,10 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpLStatRequest : SftpRequest + internal sealed class SftpLStatRequest : SftpRequest { - private byte[] _path; private readonly Action _attrsAction; + private byte[] _path; public override SftpMessageTypes SftpMessageType { @@ -61,8 +61,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var attrsResponse = response as SftpAttrsResponse; - if (attrsResponse != null) + if (response is SftpAttrsResponse attrsResponse) { _attrsAction(attrsResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs index 04470b36f..063ad3b21 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs @@ -1,9 +1,10 @@ -using Renci.SshNet.Sftp.Responses; -using System; +using System; + +using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpLinkRequest : SftpRequest + internal sealed class SftpLinkRequest : SftpRequest { private byte[] _newLinkPath; private byte[] _existingPath; @@ -67,6 +68,7 @@ public SftpLinkRequest(uint protocolVersion, uint requestId, string newLinkPath, protected override void LoadData() { base.LoadData(); + _newLinkPath = ReadBinary(); _existingPath = ReadBinary(); IsSymLink = ReadBoolean(); @@ -75,6 +77,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(_newLinkPath); WriteBinaryString(_existingPath); Write(IsSymLink); diff --git a/src/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs index 9dc60edc8..752e88c1d 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpMkDirRequest : SftpRequest + internal sealed class SftpMkDirRequest : SftpRequest { private byte[] _path; private byte[] _attributesBytes; @@ -32,6 +32,7 @@ private byte[] AttributesBytes { _attributesBytes = Attributes.GetBytes(); } + return _attributesBytes; } } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs index 81a54b62d..cde5a7af3 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs @@ -1,13 +1,14 @@ using System; using System.Text; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpOpenDirRequest : SftpRequest + internal sealed class SftpOpenDirRequest : SftpRequest { - private byte[] _path; private readonly Action _handleAction; + private byte[] _path; public override SftpMessageTypes SftpMessageType { @@ -64,8 +65,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var handleResponse = response as SftpHandleResponse; - if (handleResponse != null) + if (response is SftpHandleResponse handleResponse) { _handleAction(handleResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs index da7a7a095..780552fbc 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs @@ -4,11 +4,11 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpOpenRequest : SftpRequest + internal sealed class SftpOpenRequest : SftpRequest { + private readonly Action _handleAction; private byte[] _fileName; private byte[] _attributes; - private readonly Action _handleAction; public override SftpMessageTypes SftpMessageType { @@ -21,7 +21,7 @@ public string Filename private set { _fileName = Encoding.GetBytes(value); } } - public Flags Flags { get; private set; } + public Flags Flags { get; } public SftpFileAttributes Attributes { @@ -29,7 +29,7 @@ public SftpFileAttributes Attributes private set { _attributes = value.GetBytes(); } } - public Encoding Encoding { get; private set; } + public Encoding Encoding { get; } /// /// Gets the size of the message in bytes. @@ -83,8 +83,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var handleResponse = response as SftpHandleResponse; - if (handleResponse != null) + if (response is SftpHandleResponse handleResponse) { _handleAction(handleResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs index 9d46c69bd..9eae83253 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs @@ -1,9 +1,10 @@ using System; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpReadDirRequest : SftpRequest + internal sealed class SftpReadDirRequest : SftpRequest { private readonly Action _nameAction; @@ -53,8 +54,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var nameResponse = response as SftpNameResponse; - if (nameResponse != null) + if (response is SftpNameResponse nameResponse) { _nameAction(nameResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs index 90e36b69b..969eca564 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs @@ -1,13 +1,14 @@ using System; using System.Text; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpReadLinkRequest : SftpRequest + internal sealed class SftpReadLinkRequest : SftpRequest { - private byte[] _path; private readonly Action _nameAction; + private byte[] _path; public override SftpMessageTypes SftpMessageType { @@ -20,7 +21,7 @@ public string Path private set { _path = Encoding.GetBytes(value); } } - public Encoding Encoding { get; private set; } + public Encoding Encoding { get; } /// /// Gets the size of the message in bytes. @@ -64,8 +65,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var nameResponse = response as SftpNameResponse; - if (nameResponse != null) + if (response is SftpNameResponse nameResponse) { _nameAction(nameResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs index 72dc92877..b413b4a3a 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs @@ -1,9 +1,10 @@ using System; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpReadRequest : SftpRequest + internal sealed class SftpReadRequest : SftpRequest { private readonly Action _dataAction; @@ -37,7 +38,7 @@ protected override int BufferCapacity } } - public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt32 length, Action dataAction, Action statusAction) + public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, ulong offset, uint length, Action dataAction, Action statusAction) : base(protocolVersion, requestId, statusAction) { Handle = handle; @@ -49,6 +50,7 @@ public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, UInt protected override void LoadData() { base.LoadData(); + Handle = ReadBinary(); Offset = ReadUInt64(); Length = ReadUInt32(); @@ -57,6 +59,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(Handle); Write(Offset); Write(Length); @@ -64,8 +67,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var dataResponse = response as SftpDataResponse; - if (dataResponse != null) + if (response is SftpDataResponse dataResponse) { _dataAction(dataResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs index 44b11e90b..52e57bbe3 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs @@ -1,13 +1,14 @@ using System; using System.Text; + using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp.Requests { - internal class SftpRealPathRequest : SftpRequest + internal sealed class SftpRealPathRequest : SftpRequest { - private byte[] _path; private readonly Action _nameAction; + private byte[] _path; public override SftpMessageTypes SftpMessageType { @@ -20,7 +21,7 @@ public string Path private set { _path = Encoding.GetBytes(value); } } - public Encoding Encoding { get; private set; } + public Encoding Encoding { get; } /// /// Gets the size of the message in bytes. @@ -43,11 +44,12 @@ public SftpRealPathRequest(uint protocolVersion, uint requestId, string path, En : base(protocolVersion, requestId, statusAction) { if (nameAction == null) - throw new ArgumentNullException("nameAction"); + { + throw new ArgumentNullException(nameof(nameAction)); + } Encoding = encoding; Path = path; - _nameAction = nameAction; } @@ -59,8 +61,7 @@ protected override void SaveData() public override void Complete(SftpResponse response) { - var nameResponse = response as SftpNameResponse; - if (nameResponse != null) + if (response is SftpNameResponse nameResponse) { _nameAction(nameResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs index a527165c9..99d072f50 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpRemoveRequest : SftpRequest + internal sealed class SftpRemoveRequest : SftpRequest { private byte[] _fileName; diff --git a/src/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs index c6cf98f16..8d7fc91a2 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpRenameRequest : SftpRequest + internal sealed class SftpRenameRequest : SftpRequest { private byte[] _oldPath; private byte[] _newPath; diff --git a/src/Renci.SshNet/Sftp/Requests/SftpRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpRequest.cs index 88458e5fa..a3e4d0595 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpRequest.cs @@ -7,9 +7,9 @@ internal abstract class SftpRequest : SftpMessage { private readonly Action _statusAction; - public uint RequestId { get; private set; } - - public uint ProtocolVersion { get; private set; } + public uint RequestId { get; } + + public uint ProtocolVersion { get; } /// /// Gets the size of the message in bytes. @@ -36,8 +36,7 @@ protected SftpRequest(uint protocolVersion, uint requestId, Action _attrsAction; + private byte[] _path; public override SftpMessageTypes SftpMessageType { @@ -20,7 +20,7 @@ public string Path private set { _path = Encoding.GetBytes(value); } } - public Encoding Encoding { get; private set; } + public Encoding Encoding { get; } /// /// Gets the size of the message in bytes. @@ -50,19 +50,20 @@ public SftpStatRequest(uint protocolVersion, uint requestId, string path, Encodi protected override void LoadData() { base.LoadData(); + _path = ReadBinary(); } protected override void SaveData() { base.SaveData(); + WriteBinaryString(_path); } public override void Complete(SftpResponse response) { - var attrsResponse = response as SftpAttrsResponse; - if (attrsResponse != null) + if (response is SftpAttrsResponse attrsResponse) { _attrsAction(attrsResponse); } diff --git a/src/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs index b338923ee..63127cdd5 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpSymLinkRequest.cs @@ -4,7 +4,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpSymLinkRequest : SftpRequest + internal sealed class SftpSymLinkRequest : SftpRequest { private byte[] _newLinkPath; private byte[] _existingPath; diff --git a/src/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs index 7f4a2147a..6dff38360 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpUnblockRequest : SftpRequest + internal sealed class SftpUnblockRequest : SftpRequest { public override SftpMessageTypes SftpMessageType { @@ -35,7 +35,7 @@ protected override int BufferCapacity } } - public SftpUnblockRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt64 length, Action statusAction) + public SftpUnblockRequest(uint protocolVersion, uint requestId, byte[] handle, ulong offset, ulong length, Action statusAction) : base(protocolVersion, requestId, statusAction) { Handle = handle; @@ -46,6 +46,7 @@ public SftpUnblockRequest(uint protocolVersion, uint requestId, byte[] handle, U protected override void LoadData() { base.LoadData(); + Handle = ReadBinary(); Offset = ReadUInt64(); Length = ReadUInt64(); @@ -54,6 +55,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(Handle); Write(Offset); Write(Length); diff --git a/src/Renci.SshNet/Sftp/Requests/SftpWriteRequest.cs b/src/Renci.SshNet/Sftp/Requests/SftpWriteRequest.cs index 6e8ca3166..be7f6da91 100644 --- a/src/Renci.SshNet/Sftp/Requests/SftpWriteRequest.cs +++ b/src/Renci.SshNet/Sftp/Requests/SftpWriteRequest.cs @@ -3,7 +3,7 @@ namespace Renci.SshNet.Sftp.Requests { - internal class SftpWriteRequest : SftpRequest + internal sealed class SftpWriteRequest : SftpRequest { public override SftpMessageTypes SftpMessageType { @@ -81,6 +81,7 @@ public SftpWriteRequest(uint protocolVersion, protected override void LoadData() { base.LoadData(); + Handle = ReadBinary(); ServerFileOffset = ReadUInt64(); Data = ReadBinary(); @@ -91,6 +92,7 @@ protected override void LoadData() protected override void SaveData() { base.SaveData(); + WriteBinaryString(Handle); Write(ServerFileOffset); WriteBinary(Data, Offset, Length); diff --git a/src/Renci.SshNet/Sftp/Responses/ExtendedReplies/StatVfsReplyInfo.cs b/src/Renci.SshNet/Sftp/Responses/ExtendedReplies/StatVfsReplyInfo.cs index 71c45dc15..768764419 100644 --- a/src/Renci.SshNet/Sftp/Responses/ExtendedReplies/StatVfsReplyInfo.cs +++ b/src/Renci.SshNet/Sftp/Responses/ExtendedReplies/StatVfsReplyInfo.cs @@ -2,7 +2,7 @@ namespace Renci.SshNet.Sftp.Responses { - internal class StatVfsReplyInfo : ExtendedReplyInfo + internal sealed class StatVfsReplyInfo : ExtendedReplyInfo { public SftpFileSytemInformation Information { get; private set; } @@ -22,4 +22,4 @@ public override void LoadData(SshDataStream stream) ); } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs index fbf3250e9..f26aa5d33 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpAttrsResponse.cs @@ -1,6 +1,6 @@ namespace Renci.SshNet.Sftp.Responses { - internal class SftpAttrsResponse : SftpResponse + internal sealed class SftpAttrsResponse : SftpResponse { public override SftpMessageTypes SftpMessageType { @@ -17,6 +17,7 @@ public SftpAttrsResponse(uint protocolVersion) protected override void LoadData() { base.LoadData(); + Attributes = ReadAttributes(); } } diff --git a/src/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs index f15a8dcc0..ce0d414c5 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpDataResponse.cs @@ -1,6 +1,6 @@ namespace Renci.SshNet.Sftp.Responses { - internal class SftpDataResponse : SftpResponse + internal sealed class SftpDataResponse : SftpResponse { public override SftpMessageTypes SftpMessageType { diff --git a/src/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs index 233e3e371..31da2e937 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpHandleResponse.cs @@ -1,6 +1,6 @@ namespace Renci.SshNet.Sftp.Responses { - internal class SftpHandleResponse : SftpResponse + internal sealed class SftpHandleResponse : SftpResponse { public override SftpMessageTypes SftpMessageType { diff --git a/src/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs index 3750119d4..059831052 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpNameResponse.cs @@ -1,10 +1,11 @@ -using Renci.SshNet.Common; -using System.Collections.Generic; +using System.Collections.Generic; using System.Text; +using Renci.SshNet.Common; + namespace Renci.SshNet.Sftp.Responses { - internal class SftpNameResponse : SftpResponse + internal sealed class SftpNameResponse : SftpResponse { public override SftpMessageTypes SftpMessageType { @@ -27,7 +28,7 @@ public SftpNameResponse(uint protocolVersion, Encoding encoding) protected override void LoadData() { base.LoadData(); - + Count = ReadUInt32(); Files = new KeyValuePair[Count]; @@ -36,8 +37,9 @@ protected override void LoadData() var fileName = ReadString(Encoding); if (SupportsLongName(ProtocolVersion)) { - ReadString(Encoding); // skip longname + _ = ReadString(Encoding); // skip longname } + Files[i] = new KeyValuePair(fileName, ReadAttributes()); } } diff --git a/src/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs index f41692f04..2f43cdc37 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpStatusResponse.cs @@ -1,6 +1,6 @@ namespace Renci.SshNet.Sftp.Responses { - internal class SftpStatusResponse : SftpResponse + internal sealed class SftpStatusResponse : SftpResponse { public override SftpMessageTypes SftpMessageType { diff --git a/src/Renci.SshNet/Sftp/Responses/SftpVersionResponse.cs b/src/Renci.SshNet/Sftp/Responses/SftpVersionResponse.cs index 87c9f13f3..1ae8e6d6a 100644 --- a/src/Renci.SshNet/Sftp/Responses/SftpVersionResponse.cs +++ b/src/Renci.SshNet/Sftp/Responses/SftpVersionResponse.cs @@ -2,7 +2,7 @@ namespace Renci.SshNet.Sftp.Responses { - internal class SftpVersionResponse : SftpMessage + internal sealed class SftpVersionResponse : SftpMessage { public override SftpMessageTypes SftpMessageType { @@ -16,6 +16,7 @@ public override SftpMessageTypes SftpMessageType protected override void LoadData() { base.LoadData(); + Version = ReadUInt32(); Extentions = ReadExtensionPair(); } @@ -25,8 +26,11 @@ protected override void SaveData() base.SaveData(); Write(Version); + if (Extentions != null) + { Write(Extentions); + } } } } diff --git a/src/Renci.SshNet/Sftp/SFtpStatAsyncResult.cs b/src/Renci.SshNet/Sftp/SFtpStatAsyncResult.cs index d3776ce21..41d915499 100644 --- a/src/Renci.SshNet/Sftp/SFtpStatAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SFtpStatAsyncResult.cs @@ -1,11 +1,13 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Sftp { - internal class SFtpStatAsyncResult : AsyncResult + internal sealed class SFtpStatAsyncResult : AsyncResult { - public SFtpStatAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) + public SFtpStatAsyncResult(AsyncCallback asyncCallback, object state) + : base(asyncCallback, state) { } } diff --git a/src/Renci.SshNet/Sftp/SftpCloseAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpCloseAsyncResult.cs index 6349371f0..d4148e5c7 100644 --- a/src/Renci.SshNet/Sftp/SftpCloseAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpCloseAsyncResult.cs @@ -1,11 +1,13 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Sftp { - internal class SftpCloseAsyncResult : AsyncResult + internal sealed class SftpCloseAsyncResult : AsyncResult { - public SftpCloseAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) + public SftpCloseAsyncResult(AsyncCallback asyncCallback, object state) + : base(asyncCallback, state) { } } diff --git a/src/Renci.SshNet/Sftp/SftpFile.cs b/src/Renci.SshNet/Sftp/SftpFile.cs index 6356d26ce..07d1039e1 100644 --- a/src/Renci.SshNet/Sftp/SftpFile.cs +++ b/src/Renci.SshNet/Sftp/SftpFile.cs @@ -5,7 +5,7 @@ namespace Renci.SshNet.Sftp { /// - /// Represents SFTP file information + /// Represents SFTP file information. /// public sealed class SftpFile : ISftpFile { @@ -26,31 +26,44 @@ public sealed class SftpFile : ISftpFile internal SftpFile(ISftpSession sftpSession, string fullName, SftpFileAttributes attributes) { if (sftpSession == null) + { throw new SshConnectionException("Client not connected."); + } if (attributes == null) - throw new ArgumentNullException("attributes"); + { + throw new ArgumentNullException(nameof(attributes)); + } if (fullName == null) - throw new ArgumentNullException("fullName"); + { + throw new ArgumentNullException(nameof(fullName)); + } _sftpSession = sftpSession; Attributes = attributes; - Name = fullName.Substring(fullName.LastIndexOf('/') + 1); - FullName = fullName; } /// - /// Gets the full path of the directory or file. + /// Gets the full path of the file or directory. /// + /// + /// The full path of the file or directory. + /// public string FullName { get; private set; } /// - /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists. - /// Otherwise, the Name property gets the name of the directory. + /// Gets the name of the file or directory. /// + /// + /// The name of the file or directory. + /// + /// + /// For directories, this is the name of the last directory in the hierarchy if a hierarchy exists; + /// otherwise, the name of the directory. + /// public string Name { get; private set; } /// @@ -126,7 +139,7 @@ public DateTime LastWriteTimeUtc } /// - /// Gets or sets the size, in bytes, of the current file. + /// Gets the size, in bytes, of the current file. /// /// /// The size of the current file in bytes. @@ -179,7 +192,7 @@ public int GroupId /// Gets a value indicating whether file represents a socket. /// /// - /// true if file represents a socket; otherwise, false. + /// true if file represents a socket; otherwise, false. /// public bool IsSocket { @@ -193,7 +206,7 @@ public bool IsSocket /// Gets a value indicating whether file represents a symbolic link. /// /// - /// true if file represents a symbolic link; otherwise, false. + /// true if file represents a symbolic link; otherwise, false. /// public bool IsSymbolicLink { @@ -207,7 +220,7 @@ public bool IsSymbolicLink /// Gets a value indicating whether file represents a regular file. /// /// - /// true if file represents a regular file; otherwise, false. + /// true if file represents a regular file; otherwise, false. /// public bool IsRegularFile { @@ -221,7 +234,7 @@ public bool IsRegularFile /// Gets a value indicating whether file represents a block device. /// /// - /// true if file represents a block device; otherwise, false. + /// true if file represents a block device; otherwise, false. /// public bool IsBlockDevice { @@ -235,7 +248,7 @@ public bool IsBlockDevice /// Gets a value indicating whether file represents a directory. /// /// - /// true if file represents a directory; otherwise, false. + /// true if file represents a directory; otherwise, false. /// public bool IsDirectory { @@ -249,7 +262,7 @@ public bool IsDirectory /// Gets a value indicating whether file represents a character device. /// /// - /// true if file represents a character device; otherwise, false. + /// true if file represents a character device; otherwise, false. /// public bool IsCharacterDevice { @@ -263,7 +276,7 @@ public bool IsCharacterDevice /// Gets a value indicating whether file represents a named pipe. /// /// - /// true if file represents a named pipe; otherwise, false. + /// true if file represents a named pipe; otherwise, false. /// public bool IsNamedPipe { @@ -277,7 +290,7 @@ public bool IsNamedPipe /// Gets or sets a value indicating whether the owner can read from this file. /// /// - /// true if owner can read from this file; otherwise, false. + /// true if owner can read from this file; otherwise, false. /// public bool OwnerCanRead { @@ -295,7 +308,7 @@ public bool OwnerCanRead /// Gets or sets a value indicating whether the owner can write into this file. /// /// - /// true if owner can write into this file; otherwise, false. + /// true if owner can write into this file; otherwise, false. /// public bool OwnerCanWrite { @@ -313,7 +326,7 @@ public bool OwnerCanWrite /// Gets or sets a value indicating whether the owner can execute this file. /// /// - /// true if owner can execute this file; otherwise, false. + /// true if owner can execute this file; otherwise, false. /// public bool OwnerCanExecute { @@ -331,7 +344,7 @@ public bool OwnerCanExecute /// Gets or sets a value indicating whether the group members can read from this file. /// /// - /// true if group members can read from this file; otherwise, false. + /// true if group members can read from this file; otherwise, false. /// public bool GroupCanRead { @@ -349,7 +362,7 @@ public bool GroupCanRead /// Gets or sets a value indicating whether the group members can write into this file. /// /// - /// true if group members can write into this file; otherwise, false. + /// true if group members can write into this file; otherwise, false. /// public bool GroupCanWrite { @@ -367,7 +380,7 @@ public bool GroupCanWrite /// Gets or sets a value indicating whether the group members can execute this file. /// /// - /// true if group members can execute this file; otherwise, false. + /// true if group members can execute this file; otherwise, false. /// public bool GroupCanExecute { @@ -385,7 +398,7 @@ public bool GroupCanExecute /// Gets or sets a value indicating whether the others can read from this file. /// /// - /// true if others can read from this file; otherwise, false. + /// true if others can read from this file; otherwise, false. /// public bool OthersCanRead { @@ -403,7 +416,7 @@ public bool OthersCanRead /// Gets or sets a value indicating whether the others can write into this file. /// /// - /// true if others can write into this file; otherwise, false. + /// true if others can write into this file; otherwise, false. /// public bool OthersCanWrite { @@ -421,7 +434,7 @@ public bool OthersCanWrite /// Gets or sets a value indicating whether the others can execute this file. /// /// - /// true if others can execute this file; otherwise, false. + /// true if others can execute this file; otherwise, false. /// public bool OthersCanExecute { @@ -436,7 +449,7 @@ public bool OthersCanExecute } /// - /// Sets file permissions. + /// Sets file permissions. /// /// The mode. public void SetPermissions(short mode) @@ -469,7 +482,10 @@ public void Delete() public void MoveTo(string destFileName) { if (destFileName == null) - throw new ArgumentNullException("destFileName"); + { + throw new ArgumentNullException(nameof(destFileName)); + } + _sftpSession.RequestRename(FullName, destFileName); var fullPath = _sftpSession.GetCanonicalPath(destFileName); @@ -488,14 +504,21 @@ public void UpdateStatus() } /// - /// Returns a that represents this instance. + /// Returns a that represents this instance. /// /// - /// A that represents this instance. + /// A that represents this instance. /// public override string ToString() { - return string.Format(CultureInfo.CurrentCulture, "Name {0}, Length {1}, User ID {2}, Group ID {3}, Accessed {4}, Modified {5}", Name, Length, UserId, GroupId, LastAccessTime, LastWriteTime); + return string.Format(CultureInfo.CurrentCulture, + "Name {0}, Length {1}, User ID {2}, Group ID {3}, Accessed {4}, Modified {5}", + Name, + Length, + UserId, + GroupId, + LastAccessTime, + LastWriteTime); } } } diff --git a/src/Renci.SshNet/Sftp/SftpFileAttributes.cs b/src/Renci.SshNet/Sftp/SftpFileAttributes.cs index 573deb92a..901d6ee5a 100644 --- a/src/Renci.SshNet/Sftp/SftpFileAttributes.cs +++ b/src/Renci.SshNet/Sftp/SftpFileAttributes.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Globalization; +using System.Linq; + using Renci.SshNet.Common; -using System.Diagnostics; namespace Renci.SshNet.Sftp { @@ -12,54 +12,45 @@ namespace Renci.SshNet.Sftp /// public class SftpFileAttributes { - #region Bitmask constants - - private const uint S_IFMT = 0xF000; // bitmask for the file type bitfields + private const uint S_IFMT = 0xF000; // bitmask for the file type bitfields - private const uint S_IFSOCK = 0xC000; // socket + private const uint S_IFSOCK = 0xC000; // socket - private const uint S_IFLNK = 0xA000; // symbolic link + private const uint S_IFLNK = 0xA000; // symbolic link - private const uint S_IFREG = 0x8000; // regular file + private const uint S_IFREG = 0x8000; // regular file - private const uint S_IFBLK = 0x6000; // block device + private const uint S_IFBLK = 0x6000; // block device - private const uint S_IFDIR = 0x4000; // directory + private const uint S_IFDIR = 0x4000; // directory - private const uint S_IFCHR = 0x2000; // character device + private const uint S_IFCHR = 0x2000; // character device - private const uint S_IFIFO = 0x1000; // FIFO + private const uint S_IFIFO = 0x1000; // FIFO - private const uint S_ISUID = 0x0800; // set UID bit + private const uint S_ISUID = 0x0800; // set UID bit - private const uint S_ISGID = 0x0400; // set-group-ID bit (see below) + private const uint S_ISGID = 0x0400; // set-group-ID bit (see below) - private const uint S_ISVTX = 0x0200; // sticky bit (see below) + private const uint S_ISVTX = 0x0200; // sticky bit (see below) - private const uint S_IRUSR = 0x0100; // owner has read permission + private const uint S_IRUSR = 0x0100; // owner has read permission - private const uint S_IWUSR = 0x0080; // owner has write permission + private const uint S_IWUSR = 0x0080; // owner has write permission - private const uint S_IXUSR = 0x0040; // owner has execute permission + private const uint S_IXUSR = 0x0040; // owner has execute permission - private const uint S_IRGRP = 0x0020; // group has read permission + private const uint S_IRGRP = 0x0020; // group has read permission - private const uint S_IWGRP = 0x0010; // group has write permission + private const uint S_IWGRP = 0x0010; // group has write permission - private const uint S_IXGRP = 0x0008; // group has execute permission + private const uint S_IXGRP = 0x0008; // group has execute permission - private const uint S_IROTH = 0x0004; // others have read permission + private const uint S_IROTH = 0x0004; // others have read permission - private const uint S_IWOTH = 0x0002; // others have write permission + private const uint S_IWOTH = 0x0002; // others have write permission - private const uint S_IXOTH = 0x0001; // others have execute permission - - #endregion - - private bool _isBitFiledsBitSet; - private bool _isUIDBitSet; - private bool _isGroupIDBitSet; - private bool _isStickyBitSet; + private const uint S_IXOTH = 0x0001; // others have execute permission private readonly DateTime _originalLastAccessTimeUtc; private readonly DateTime _originalLastWriteTimeUtc; @@ -69,6 +60,11 @@ public class SftpFileAttributes private readonly uint _originalPermissions; private readonly IDictionary _originalExtensions; + private bool _isBitFiledsBitSet; + private bool _isUIDBitSet; + private bool _isGroupIDBitSet; + private bool _isStickyBitSet; + internal bool IsLastAccessTimeChanged { get { return _originalLastAccessTimeUtc != LastAccessTimeUtc; } @@ -114,12 +110,12 @@ public DateTime LastAccessTime { get { - return ToLocalTime(this.LastAccessTimeUtc); + return ToLocalTime(LastAccessTimeUtc); } set { - this.LastAccessTimeUtc = ToUniversalTime(value); + LastAccessTimeUtc = ToUniversalTime(value); } } @@ -133,12 +129,12 @@ public DateTime LastWriteTime { get { - return ToLocalTime(this.LastWriteTimeUtc); + return ToLocalTime(LastWriteTimeUtc); } set { - this.LastWriteTimeUtc = ToUniversalTime(value); + LastWriteTimeUtc = ToUniversalTime(value); } } @@ -194,7 +190,7 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a symbolic link. /// /// - /// true if file represents a symbolic link; otherwise, false. + /// true if file represents a symbolic link; otherwise, false. /// public bool IsSymbolicLink { get; private set; } @@ -202,7 +198,7 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a regular file. /// /// - /// true if file represents a regular file; otherwise, false. + /// true if file represents a regular file; otherwise, false. /// public bool IsRegularFile { get; private set; } @@ -210,7 +206,7 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a block device. /// /// - /// true if file represents a block device; otherwise, false. + /// true if file represents a block device; otherwise, false. /// public bool IsBlockDevice { get; private set; } @@ -218,7 +214,7 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a directory. /// /// - /// true if file represents a directory; otherwise, false. + /// true if file represents a directory; otherwise, false. /// public bool IsDirectory { get; private set; } @@ -226,7 +222,7 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a character device. /// /// - /// true if file represents a character device; otherwise, false. + /// true if file represents a character device; otherwise, false. /// public bool IsCharacterDevice { get; private set; } @@ -234,84 +230,84 @@ public DateTime LastWriteTime /// Gets a value indicating whether file represents a named pipe. /// /// - /// true if file represents a named pipe; otherwise, false. + /// true if file represents a named pipe; otherwise, false. /// public bool IsNamedPipe { get; private set; } /// - /// Gets a value indicating whether the owner can read from this file. + /// Gets or sets a value indicating whether the owner can read from this file. /// /// - /// true if owner can read from this file; otherwise, false. + /// true if owner can read from this file; otherwise, false. /// public bool OwnerCanRead { get; set; } /// - /// Gets a value indicating whether the owner can write into this file. + /// Gets or sets a value indicating whether the owner can write into this file. /// /// - /// true if owner can write into this file; otherwise, false. + /// true if owner can write into this file; otherwise, false. /// public bool OwnerCanWrite { get; set; } /// - /// Gets a value indicating whether the owner can execute this file. + /// Gets or sets a value indicating whether the owner can execute this file. /// /// - /// true if owner can execute this file; otherwise, false. + /// true if owner can execute this file; otherwise, false. /// public bool OwnerCanExecute { get; set; } /// - /// Gets a value indicating whether the group members can read from this file. + /// Gets or sets a value indicating whether the group members can read from this file. /// /// - /// true if group members can read from this file; otherwise, false. + /// true if group members can read from this file; otherwise, false. /// public bool GroupCanRead { get; set; } /// - /// Gets a value indicating whether the group members can write into this file. + /// Gets or sets a value indicating whether the group members can write into this file. /// /// - /// true if group members can write into this file; otherwise, false. + /// true if group members can write into this file; otherwise, false. /// public bool GroupCanWrite { get; set; } /// - /// Gets a value indicating whether the group members can execute this file. + /// Gets or sets a value indicating whether the group members can execute this file. /// /// - /// true if group members can execute this file; otherwise, false. + /// true if group members can execute this file; otherwise, false. /// public bool GroupCanExecute { get; set; } /// - /// Gets a value indicating whether the others can read from this file. + /// Gets or sets a value indicating whether the others can read from this file. /// /// - /// true if others can read from this file; otherwise, false. + /// true if others can read from this file; otherwise, false. /// public bool OthersCanRead { get; set; } /// - /// Gets a value indicating whether the others can write into this file. + /// Gets or sets a value indicating whether the others can write into this file. /// /// - /// true if others can write into this file; otherwise, false. + /// true if others can write into this file; otherwise, false. /// public bool OthersCanWrite { get; set; } /// - /// Gets a value indicating whether the others can execute this file. + /// Gets or sets a value indicating whether the others can execute this file. /// /// - /// true if others can execute this file; otherwise, false. + /// true if others can execute this file; otherwise, false. /// public bool OthersCanExecute { get; set; } /// - /// Gets or sets the extensions. + /// Gets the extensions. /// /// /// The extensions. @@ -325,108 +321,148 @@ internal uint Permissions uint permission = 0; if (_isBitFiledsBitSet) - permission = permission | S_IFMT; + { + permission |= S_IFMT; + } if (IsSocket) - permission = permission | S_IFSOCK; + { + permission |= S_IFSOCK; + } if (IsSymbolicLink) - permission = permission | S_IFLNK; + { + permission |= S_IFLNK; + } if (IsRegularFile) - permission = permission | S_IFREG; + { + permission |= S_IFREG; + } if (IsBlockDevice) - permission = permission | S_IFBLK; + { + permission |= S_IFBLK; + } if (IsDirectory) - permission = permission | S_IFDIR; + { + permission |= S_IFDIR; + } if (IsCharacterDevice) - permission = permission | S_IFCHR; + { + permission |= S_IFCHR; + } if (IsNamedPipe) - permission = permission | S_IFIFO; + { + permission |= S_IFIFO; + } if (_isUIDBitSet) - permission = permission | S_ISUID; + { + permission |= S_ISUID; + } if (_isGroupIDBitSet) - permission = permission | S_ISGID; + { + permission |= S_ISGID; + } if (_isStickyBitSet) - permission = permission | S_ISVTX; + { + permission |= S_ISVTX; + } if (OwnerCanRead) - permission = permission | S_IRUSR; + { + permission |= S_IRUSR; + } if (OwnerCanWrite) - permission = permission | S_IWUSR; + { + permission |= S_IWUSR; + } if (OwnerCanExecute) - permission = permission | S_IXUSR; + { + permission |= S_IXUSR; + } if (GroupCanRead) - permission = permission | S_IRGRP; + { + permission |= S_IRGRP; + } if (GroupCanWrite) - permission = permission | S_IWGRP; + { + permission |= S_IWGRP; + } if (GroupCanExecute) - permission = permission | S_IXGRP; + { + permission |= S_IXGRP; + } if (OthersCanRead) - permission = permission | S_IROTH; + { + permission |= S_IROTH; + } if (OthersCanWrite) - permission = permission | S_IWOTH; + { + permission |= S_IWOTH; + } if (OthersCanExecute) - permission = permission | S_IXOTH; + { + permission |= S_IXOTH; + } return permission; } private set { - _isBitFiledsBitSet = ((value & S_IFMT) == S_IFMT); + _isBitFiledsBitSet = (value & S_IFMT) == S_IFMT; - IsSocket = ((value & S_IFSOCK) == S_IFSOCK); + IsSocket = (value & S_IFSOCK) == S_IFSOCK; - IsSymbolicLink = ((value & S_IFLNK) == S_IFLNK); + IsSymbolicLink = (value & S_IFLNK) == S_IFLNK; - IsRegularFile = ((value & S_IFREG) == S_IFREG); + IsRegularFile = (value & S_IFREG) == S_IFREG; - IsBlockDevice = ((value & S_IFBLK) == S_IFBLK); + IsBlockDevice = (value & S_IFBLK) == S_IFBLK; - IsDirectory = ((value & S_IFDIR) == S_IFDIR); + IsDirectory = (value & S_IFDIR) == S_IFDIR; - IsCharacterDevice = ((value & S_IFCHR) == S_IFCHR); + IsCharacterDevice = (value & S_IFCHR) == S_IFCHR; - IsNamedPipe = ((value & S_IFIFO) == S_IFIFO); + IsNamedPipe = (value & S_IFIFO) == S_IFIFO; - _isUIDBitSet = ((value & S_ISUID) == S_ISUID); + _isUIDBitSet = (value & S_ISUID) == S_ISUID; - _isGroupIDBitSet = ((value & S_ISGID) == S_ISGID); + _isGroupIDBitSet = (value & S_ISGID) == S_ISGID; - _isStickyBitSet = ((value & S_ISVTX) == S_ISVTX); + _isStickyBitSet = (value & S_ISVTX) == S_ISVTX; - OwnerCanRead = ((value & S_IRUSR) == S_IRUSR); + OwnerCanRead = (value & S_IRUSR) == S_IRUSR; - OwnerCanWrite = ((value & S_IWUSR) == S_IWUSR); + OwnerCanWrite = (value & S_IWUSR) == S_IWUSR; - OwnerCanExecute = ((value & S_IXUSR) == S_IXUSR); + OwnerCanExecute = (value & S_IXUSR) == S_IXUSR; - GroupCanRead = ((value & S_IRGRP) == S_IRGRP); + GroupCanRead = (value & S_IRGRP) == S_IRGRP; - GroupCanWrite = ((value & S_IWGRP) == S_IWGRP); + GroupCanWrite = (value & S_IWGRP) == S_IWGRP; - GroupCanExecute = ((value & S_IXGRP) == S_IXGRP); + GroupCanExecute = (value & S_IXGRP) == S_IXGRP; - OthersCanRead = ((value & S_IROTH) == S_IROTH); + OthersCanRead = (value & S_IROTH) == S_IROTH; - OthersCanWrite = ((value & S_IWOTH) == S_IWOTH); + OthersCanWrite = (value & S_IWOTH) == S_IWOTH; - OthersCanExecute = ((value & S_IXOTH) == S_IXOTH); + OthersCanExecute = (value & S_IXOTH) == S_IXOTH; } } @@ -451,9 +487,9 @@ internal SftpFileAttributes(DateTime lastAccessTimeUtc, DateTime lastWriteTimeUt /// The mode. public void SetPermissions(short mode) { - if (mode < 0 || mode > 999) + if (mode is < 0 or > 999) { - throw new ArgumentOutOfRangeException("mode"); + throw new ArgumentOutOfRangeException(nameof(mode)); } var modeBytes = mode.ToString(CultureInfo.InvariantCulture).PadLeft(3, '0').ToCharArray(); @@ -562,26 +598,26 @@ internal static SftpFileAttributes FromBytes(SshDataStream stream) uint permissions = 0; DateTime accessTime; DateTime modifyTime; - IDictionary extensions = null; + Dictionary extensions = null; - if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE + if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE { size = (long) stream.ReadUInt64(); } - if ((flag & 0x00000002) == 0x00000002) // SSH_FILEXFER_ATTR_UIDGID + if ((flag & 0x00000002) == 0x00000002) // SSH_FILEXFER_ATTR_UIDGID { userId = (int) stream.ReadUInt32(); groupId = (int) stream.ReadUInt32(); } - if ((flag & 0x00000004) == 0x00000004) // SSH_FILEXFER_ATTR_PERMISSIONS + if ((flag & 0x00000004) == 0x00000004) // SSH_FILEXFER_ATTR_PERMISSIONS { permissions = stream.ReadUInt32(); } - if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME + if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME { // The incoming times are "Unix times", so they're already in UTC. We need to preserve that // to avoid losing information in a local time conversion during the "fall back" hour in DST. @@ -596,7 +632,7 @@ internal static SftpFileAttributes FromBytes(SshDataStream stream) modifyTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc); } - if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_EXTENDED + if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_EXTENDED { var extendedCount = (int) stream.ReadUInt32(); extensions = new Dictionary(extendedCount); diff --git a/src/Renci.SshNet/Sftp/SftpFileReader.cs b/src/Renci.SshNet/Sftp/SftpFileReader.cs index a881e9c03..a6a1f0898 100644 --- a/src/Renci.SshNet/Sftp/SftpFileReader.cs +++ b/src/Renci.SshNet/Sftp/SftpFileReader.cs @@ -1,10 +1,11 @@ -using Renci.SshNet.Abstractions; -using Renci.SshNet.Common; -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Threading; +using Renci.SshNet.Abstractions; +using Renci.SshNet.Common; + namespace Renci.SshNet.Sftp { internal class SftpFileReader : ISftpFileReader @@ -14,42 +15,43 @@ internal class SftpFileReader : ISftpFileReader private readonly byte[] _handle; private readonly ISftpSession _sftpSession; private readonly uint _chunkSize; - private ulong _offset; + private readonly SemaphoreLight _semaphore; + private readonly object _readLock; + private readonly ManualResetEvent _disposingWaitHandle; + private readonly ManualResetEvent _readAheadCompleted; + private readonly Dictionary _queue; + private readonly WaitHandle[] _waitHandles; /// /// Holds the size of the file, when available. /// private readonly long? _fileSize; - private readonly Dictionary _queue; - private readonly WaitHandle[] _waitHandles; + private ulong _offset; private int _readAheadChunkIndex; private ulong _readAheadOffset; - private readonly ManualResetEvent _readAheadCompleted; private int _nextChunkIndex; /// /// Holds a value indicating whether EOF has already been signaled by the SSH server. /// private bool _endOfFileReceived; + /// /// Holds a value indicating whether the client has read up to the end of the file. /// private bool _isEndOfFileRead; - private readonly SemaphoreLight _semaphore; - private readonly object _readLock; - private readonly ManualResetEvent _disposingWaitHandle; private bool _disposingOrDisposed; private Exception _exception; /// - /// Initializes a new instance with the specified handle, + /// Initializes a new instance of the class with the specified handle, /// and the maximum number of pending reads. /// - /// - /// + /// The file handle. + /// The SFT session. /// The size of a individual read-ahead chunk. /// The maximum number of pending reads. /// The size of the file, if known; otherwise, null. @@ -72,11 +74,19 @@ public SftpFileReader(byte[] handle, ISftpSession sftpSession, uint chunkSize, i public byte[] Read() { if (_disposingOrDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } + if (_exception != null) + { throw _exception; + } + if (_isEndOfFileRead) + { throw new SshException("Attempting to read beyond the end of the file."); + } BufferedRead nextChunk; @@ -86,12 +96,14 @@ public byte[] Read() // instance is already disposed while (!_queue.TryGetValue(_nextChunkIndex, out nextChunk) && _exception == null) { - Monitor.Wait(_readLock); + _ =Monitor.Wait(_readLock); } // throw when exception occured in read-ahead, or the current instance is already disposed if (_exception != null) + { throw _exception; + } var data = nextChunk.Data; @@ -101,20 +113,22 @@ public byte[] Read() if (data.Length == 0) { // PERF: we do not bother updating all of the internal state when we've reached EOF - _isEndOfFileRead = true; } else { // remove processed chunk - _queue.Remove(_nextChunkIndex); + _ = _queue.Remove(_nextChunkIndex); + // update offset _offset += (ulong) data.Length; + // move to next chunk _nextChunkIndex++; } + // unblock wait in read-ahead - _semaphore.Release(); + _ = _semaphore.Release(); return data; } @@ -126,26 +140,30 @@ public byte[] Read() { // avoid future reads _isEndOfFileRead = true; + // unblock wait in read-ahead - _semaphore.Release(); + _ = _semaphore.Release(); + // signal EOF to caller return nextChunk.Data; } } - // When the server returned less bytes than requested (for the previous chunk) - // we'll synchronously request the remaining data. - // - // Due to the optimization above, we'll only get here in one of the following cases: - // - an EOF situation for files for which we were unable to obtain the file size - // - fewer bytes that requested were returned - // - // According to the SSH specification, this last case should never happen for normal - // disk files (but can happen for device files). In practice, OpenSSH - for example - - // returns less bytes than requested when requesting more than 64 KB. - // - // Important: - // To avoid a deadlock, this read must be done outside of the read lock + /* + * When the server returned less bytes than requested (for the previous chunk) + * we'll synchronously request the remaining data. + * + * Due to the optimization above, we'll only get here in one of the following cases: + * - an EOF situation for files for which we were unable to obtain the file size + * - fewer bytes that requested were returned + * + * According to the SSH specification, this last case should never happen for normal + * disk files (but can happen for device files). In practice, OpenSSH - for example - + * returns less bytes than requested when requesting more than 64 KB. + * + * Important: + * To avoid a deadlock, this read must be done outside of the read lock. + */ var bytesToCatchUp = nextChunk.Offset - _offset; @@ -162,24 +180,28 @@ public byte[] Read() if (nextChunk.Data.Length == 0) { _isEndOfFileRead = true; + // ensure we've not yet disposed the current instance if (!_disposingOrDisposed) { // unblock wait in read-ahead - _semaphore.Release(); + _ = _semaphore.Release(); } + // signal EOF to caller return read; } // move reader to error state _exception = new SshException("Unexpectedly reached end of file."); + // ensure we've not yet disposed the current instance if (!_disposingOrDisposed) { // unblock wait in read-ahead - _semaphore.Release(); + _ = _semaphore.Release(); } + // notify caller of error throw _exception; } @@ -202,13 +224,15 @@ public void Dispose() } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected void Dispose(bool disposing) { if (_disposingOrDisposed) + { return; + } // transition to disposing state _disposingOrDisposed = true; @@ -219,10 +243,10 @@ protected void Dispose(bool disposing) _exception = new ObjectDisposedException(GetType().FullName); // signal that we're disposing to interrupt wait in read-ahead - _disposingWaitHandle.Set(); + _ = _disposingWaitHandle.Set(); // wait until the read-ahead thread has completed - _readAheadCompleted.WaitOne(); + _ = _readAheadCompleted.WaitOne(); // unblock the Read() lock (_readLock) @@ -230,6 +254,7 @@ protected void Dispose(bool disposing) // dispose semaphore in read lock to ensure we don't run into an ObjectDisposedException // in Read() _semaphore.Dispose(); + // awake Read Monitor.PulseAll(_readLock); } @@ -269,6 +294,7 @@ private void StartReadAhead() { Monitor.PulseAll(_readLock); } + // break the read-ahead loop break; } @@ -285,7 +311,9 @@ private void StartReadAhead() // don't bother reading any more chunks if we received EOF, an exception has occurred // or the current instance is disposed if (_endOfFileReceived || _exception != null) + { break; + } // start reading next chunk var bufferedRead = new BufferedRead(_readAheadChunkIndex, _readAheadOffset); @@ -301,14 +329,13 @@ private void StartReadAhead() // mode to avoid having multiple read-aheads that read beyond EOF if (_fileSize != null && (long) _readAheadOffset > _fileSize.Value) { - var asyncResult = _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, null, - bufferedRead); + var asyncResult = _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, null, bufferedRead); var data = _sftpSession.EndRead(asyncResult); ReadCompletedCore(bufferedRead, data); } else { - _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, ReadCompleted, bufferedRead); + _ = _sftpSession.BeginRead(_handle, _readAheadOffset, _chunkSize, ReadCompleted, bufferedRead); } } catch (Exception ex) @@ -319,11 +346,12 @@ private void StartReadAhead() // advance read-ahead offset _readAheadOffset += _chunkSize; + // increment index of read-ahead chunk _readAheadChunkIndex++; } - _readAheadCompleted.Set(); + _ = _readAheadCompleted.Set(); }); } @@ -350,7 +378,7 @@ private bool ContinueReadAhead() } catch (Exception ex) { - Interlocked.CompareExchange(ref _exception, ex, null); + _ = Interlocked.CompareExchange(ref _exception, ex, comparand: null); return false; } } @@ -392,6 +420,7 @@ private void ReadCompletedCore(BufferedRead bufferedRead, byte[] data) { // add item to queue _queue.Add(bufferedRead.ChunkIndex, bufferedRead); + // signal that a chunk has been read or EOF has been reached; // in both cases, Read() will eventually also unblock the "read-ahead" thread Monitor.PulseAll(_readLock); @@ -407,10 +436,10 @@ private void ReadCompletedCore(BufferedRead bufferedRead, byte[] data) private void HandleFailure(Exception cause) { - Interlocked.CompareExchange(ref _exception, cause, null); + _ = Interlocked.CompareExchange(ref _exception, cause, comparand: null); // unblock read-ahead - _semaphore.Release(); + _ = _semaphore.Release(); // unblock Read() lock (_readLock) @@ -419,13 +448,13 @@ private void HandleFailure(Exception cause) } } - internal class BufferedRead + internal sealed class BufferedRead { - public int ChunkIndex { get; private set; } + public int ChunkIndex { get; } public byte[] Data { get; private set; } - public ulong Offset { get; private set; } + public ulong Offset { get; } public BufferedRead(int chunkIndex, ulong offset) { diff --git a/src/Renci.SshNet/Sftp/SftpFileStream.cs b/src/Renci.SshNet/Sftp/SftpFileStream.cs index a266b35b8..e42cad978 100644 --- a/src/Renci.SshNet/Sftp/SftpFileStream.cs +++ b/src/Renci.SshNet/Sftp/SftpFileStream.cs @@ -1,10 +1,11 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Threading; -using System.Diagnostics.CodeAnalysis; -using Renci.SshNet.Common; using System.Threading.Tasks; +using Renci.SshNet.Common; + namespace Renci.SshNet.Sftp { /// @@ -13,15 +14,16 @@ namespace Renci.SshNet.Sftp /// public class SftpFileStream : Stream { - // TODO: Add security method to set userid, groupid and other permission settings + private readonly object _lock = new object(); + private readonly int _readBufferSize; + private readonly int _writeBufferSize; + // Internal state. private byte[] _handle; private ISftpSession _session; // Buffer information. - private readonly int _readBufferSize; private byte[] _readBuffer; - private readonly int _writeBufferSize; private byte[] _writeBuffer; private int _bufferPosition; private int _bufferLen; @@ -31,8 +33,6 @@ public class SftpFileStream : Stream private bool _canSeek; private bool _canWrite; - private readonly object _lock = new object(); - /// /// Gets a value indicating whether the current stream supports reading. /// @@ -67,7 +67,7 @@ public override bool CanWrite } /// - /// Indicates whether timeout properties are usable for . + /// Gets a value indicating whether timeout properties are usable for . /// /// /// true in all cases. @@ -95,7 +95,9 @@ public override long Length CheckSessionIsOpen(); if (!CanSeek) + { throw new NotSupportedException("Seek operation is not supported."); + } // Flush the write buffer, because it may // affect the length of the stream. @@ -105,11 +107,12 @@ public override long Length } // obtain file attributes - var attributes = _session.RequestFStat(_handle, true); + var attributes = _session.RequestFStat(_handle, nullOnError: true); if (attributes != null) { return attributes.Size; } + throw new IOException("Seek operation failed."); } } @@ -127,13 +130,17 @@ public override long Position get { CheckSessionIsOpen(); + if (!CanSeek) + { throw new NotSupportedException("Seek operation not supported."); + } + return _position; } set { - Seek(value, SeekOrigin.Begin); + _ = Seek(value, SeekOrigin.Begin); } } @@ -180,12 +187,14 @@ private SftpFileStream(ISftpSession session, string path, FileAccess access, int _handle = handle; - // instead of using the specified buffer size as is, we use it to calculate a buffer size - // that ensures we always receive or send the max. number of bytes in a single SSH_FXP_READ - // or SSH_FXP_WRITE message + /* + * Instead of using the specified buffer size as is, we use it to calculate a buffer size + * that ensures we always receive or send the max. number of bytes in a single SSH_FXP_READ + * or SSH_FXP_WRITE message. + */ - _readBufferSize = (int)session.CalculateOptimalReadLength((uint)bufferSize); - _writeBufferSize = (int)session.CalculateOptimalWriteLength((uint)bufferSize, _handle); + _readBufferSize = (int) session.CalculateOptimalReadLength((uint)bufferSize); + _writeBufferSize = (int) session.CalculateOptimalWriteLength((uint)bufferSize, _handle); _position = position; } @@ -193,11 +202,19 @@ private SftpFileStream(ISftpSession session, string path, FileAccess access, int internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAccess access, int bufferSize) { if (session == null) + { throw new SshConnectionException("Client not connected."); + } + if (path == null) - throw new ArgumentNullException("path"); + { + throw new ArgumentNullException(nameof(path)); + } + if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", "Cannot be less than or equal to zero."); + { + throw new ArgumentOutOfRangeException(nameof(bufferSize), "Cannot be less than or equal to zero."); + } Timeout = TimeSpan.FromSeconds(30); Name = path; @@ -223,7 +240,7 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc flags |= Flags.Write; break; default: - throw new ArgumentOutOfRangeException("access"); + throw new ArgumentOutOfRangeException(nameof(access)); } if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) @@ -233,13 +250,13 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc if ((access & FileAccess.Write) == 0) { - if (mode == FileMode.Create || mode == FileMode.CreateNew || mode == FileMode.Truncate || mode == FileMode.Append) + if (mode is FileMode.Create or FileMode.CreateNew or FileMode.Truncate or FileMode.Append) { throw new ArgumentException(string.Format("Combining {0}: {1} with {2}: {3} is invalid.", - typeof(FileMode).Name, - mode, - typeof(FileAccess).Name, - access)); + nameof(FileMode), + mode, + nameof(FileAccess), + access)); } } @@ -249,7 +266,7 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc flags |= Flags.Append | Flags.CreateNewOrOpen; break; case FileMode.Create: - _handle = _session.RequestOpen(path, flags | Flags.Truncate, true); + _handle = _session.RequestOpen(path, flags | Flags.Truncate, nullOnError: true); if (_handle == null) { flags |= Flags.CreateNew; @@ -258,6 +275,7 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc { flags |= Flags.Truncate; } + break; case FileMode.CreateNew: flags |= Flags.CreateNew; @@ -271,22 +289,23 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc flags |= Flags.Truncate; break; default: - throw new ArgumentOutOfRangeException("mode"); + throw new ArgumentOutOfRangeException(nameof(mode)); } - if (_handle == null) - _handle = _session.RequestOpen(path, flags); + _handle ??= _session.RequestOpen(path, flags); - // instead of using the specified buffer size as is, we use it to calculate a buffer size - // that ensures we always receive or send the max. number of bytes in a single SSH_FXP_READ - // or SSH_FXP_WRITE message + /* + * Instead of using the specified buffer size as is, we use it to calculate a buffer size + * that ensures we always receive or send the max. number of bytes in a single SSH_FXP_READ + * or SSH_FXP_WRITE message. + */ _readBufferSize = (int) session.CalculateOptimalReadLength((uint) bufferSize); _writeBufferSize = (int) session.CalculateOptimalWriteLength((uint) bufferSize, _handle); if (mode == FileMode.Append) { - var attributes = _session.RequestFStat(_handle, false); + var attributes = _session.RequestFStat(_handle, nullOnError: false); _position = attributes.Size; } } @@ -294,11 +313,19 @@ internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAc internal static async Task OpenAsync(ISftpSession session, string path, FileMode mode, FileAccess access, int bufferSize, CancellationToken cancellationToken) { if (session == null) + { throw new SshConnectionException("Client not connected."); + } + if (path == null) - throw new ArgumentNullException("path"); + { + throw new ArgumentNullException(nameof(path)); + } + if (bufferSize <= 0) - throw new ArgumentOutOfRangeException("bufferSize", "Cannot be less than or equal to zero."); + { + throw new ArgumentOutOfRangeException(nameof(bufferSize), "Cannot be less than or equal to zero."); + } var flags = Flags.None; @@ -315,7 +342,7 @@ internal static async Task OpenAsync(ISftpSession session, strin flags |= Flags.Write; break; default: - throw new ArgumentOutOfRangeException("access"); + throw new ArgumentOutOfRangeException(nameof(access)); } if ((access & FileAccess.Read) != 0 && mode == FileMode.Append) @@ -325,18 +352,16 @@ internal static async Task OpenAsync(ISftpSession session, strin if ((access & FileAccess.Write) == 0) { - if (mode == FileMode.Create || mode == FileMode.CreateNew || mode == FileMode.Truncate || mode == FileMode.Append) + if (mode is FileMode.Create or FileMode.CreateNew or FileMode.Truncate or FileMode.Append) { throw new ArgumentException(string.Format("Combining {0}: {1} with {2}: {3} is invalid.", - typeof(FileMode).Name, - mode, - typeof(FileAccess).Name, - access)); + nameof(FileMode), + mode, + nameof(FileAccess), + access)); } } - byte[] handle = null; - switch (mode) { case FileMode.Append: @@ -357,11 +382,10 @@ internal static async Task OpenAsync(ISftpSession session, strin flags |= Flags.Truncate; break; default: - throw new ArgumentOutOfRangeException("mode"); + throw new ArgumentOutOfRangeException(nameof(mode)); } - if (handle == null) - handle = await session.RequestOpenAsync(path, flags, cancellationToken).ConfigureAwait(false); + var handle = await session.RequestOpenAsync(path, flags, cancellationToken).ConfigureAwait(false); long position = 0; if (mode == FileMode.Append) @@ -378,9 +402,10 @@ internal static async Task OpenAsync(ISftpSession session, strin await session.RequestCloseAsync(handle, cancellationToken).ConfigureAwait(false); } catch - { + { // The original exception is presumably more informative, so we just ignore this one. } + throw; } } @@ -389,12 +414,11 @@ internal static async Task OpenAsync(ISftpSession session, strin } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~SftpFileStream() { - Dispose(false); + Dispose(disposing: false); } /// @@ -434,10 +458,8 @@ public override Task FlushAsync(CancellationToken cancellationToken) { return FlushWriteBufferAsync(cancellationToken); } - else - { - FlushReadBuffer(); - } + + FlushReadBuffer(); return Task.CompletedTask; } @@ -480,13 +502,24 @@ public override int Read(byte[] buffer, int offset, int count) var readLen = 0; if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset < 0) - throw new ArgumentOutOfRangeException("offset"); + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if (count < 0) - throw new ArgumentOutOfRangeException("count"); + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + if ((buffer.Length - offset) < count) + { throw new ArgumentException("Invalid array range."); + } // Lock down the file stream while we do this. lock (_lock) @@ -518,6 +551,7 @@ public override int Read(byte[] buffer, int offset, int count) { // write all data read to caller-provided buffer bytesToWriteToCallerBuffer = data.Length; + // reset buffer since we will skip buffering _bufferPosition = 0; _bufferLen = 0; @@ -526,18 +560,23 @@ public override int Read(byte[] buffer, int offset, int count) { // determine number of bytes that we should write into read buffer var bytesToWriteToReadBuffer = data.Length - bytesToWriteToCallerBuffer; + // write remaining bytes to read buffer Buffer.BlockCopy(data, count, GetOrCreateReadBuffer(), 0, bytesToWriteToReadBuffer); + // update position in read buffer _bufferPosition = 0; + // update number of bytes in read buffer _bufferLen = bytesToWriteToReadBuffer; } // write bytes to caller-provided buffer Buffer.BlockCopy(data, 0, buffer, offset, bytesToWriteToCallerBuffer); + // update stream position _position += bytesToWriteToCallerBuffer; + // record total number of bytes read into caller-provided buffer readLen += bytesToWriteToCallerBuffer; @@ -553,6 +592,7 @@ public override int Read(byte[] buffer, int offset, int count) // advance offset to start writing bytes into caller-provided buffer offset += bytesToWriteToCallerBuffer; + // update number of bytes left to read into caller-provided buffer count -= bytesToWriteToCallerBuffer; } @@ -560,18 +600,25 @@ public override int Read(byte[] buffer, int offset, int count) { // limit the number of bytes to use from read buffer to the caller-request number of bytes if (bytesAvailableInBuffer > count) + { bytesAvailableInBuffer = count; + } // copy data from read buffer to the caller-provided buffer Buffer.BlockCopy(GetOrCreateReadBuffer(), _bufferPosition, buffer, offset, bytesAvailableInBuffer); + // update position in read buffer _bufferPosition += bytesAvailableInBuffer; + // update stream position _position += bytesAvailableInBuffer; + // record total number of bytes read into caller-provided buffer readLen += bytesAvailableInBuffer; + // advance offset to start writing bytes into caller-provided buffer offset += bytesAvailableInBuffer; + // update number of bytes left to read count -= bytesAvailableInBuffer; } @@ -596,13 +643,24 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, var readLen = 0; if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset < 0) - throw new ArgumentOutOfRangeException("offset"); + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if (count < 0) - throw new ArgumentOutOfRangeException("count"); + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + if ((buffer.Length - offset) < count) + { throw new ArgumentException("Invalid array range."); + } CheckSessionIsOpen(); @@ -631,6 +689,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, { // write all data read to caller-provided buffer bytesToWriteToCallerBuffer = data.Length; + // reset buffer since we will skip buffering _bufferPosition = 0; _bufferLen = 0; @@ -639,18 +698,23 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, { // determine number of bytes that we should write into read buffer var bytesToWriteToReadBuffer = data.Length - bytesToWriteToCallerBuffer; + // write remaining bytes to read buffer Buffer.BlockCopy(data, count, GetOrCreateReadBuffer(), 0, bytesToWriteToReadBuffer); + // update position in read buffer _bufferPosition = 0; + // update number of bytes in read buffer _bufferLen = bytesToWriteToReadBuffer; } // write bytes to caller-provided buffer Buffer.BlockCopy(data, 0, buffer, offset, bytesToWriteToCallerBuffer); + // update stream position _position += bytesToWriteToCallerBuffer; + // record total number of bytes read into caller-provided buffer readLen += bytesToWriteToCallerBuffer; @@ -666,6 +730,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, // advance offset to start writing bytes into caller-provided buffer offset += bytesToWriteToCallerBuffer; + // update number of bytes left to read into caller-provided buffer count -= bytesToWriteToCallerBuffer; } @@ -673,18 +738,25 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count, { // limit the number of bytes to use from read buffer to the caller-request number of bytes if (bytesAvailableInBuffer > count) + { bytesAvailableInBuffer = count; + } // copy data from read buffer to the caller-provided buffer Buffer.BlockCopy(GetOrCreateReadBuffer(), _bufferPosition, buffer, offset, bytesAvailableInBuffer); + // update position in read buffer _bufferPosition += bytesAvailableInBuffer; + // update stream position _position += bytesAvailableInBuffer; + // record total number of bytes read into caller-provided buffer readLen += bytesAvailableInBuffer; + // advance offset to start writing bytes into caller-provided buffer offset += bytesAvailableInBuffer; + // update number of bytes left to read count -= bytesAvailableInBuffer; } @@ -738,6 +810,7 @@ public override int ReadByte() // Extract the next byte from the buffer. ++_position; + return readBuffer[_bufferPosition++]; } } @@ -755,7 +828,7 @@ public override int ReadByte() /// Methods were called after the stream was closed. public override long Seek(long offset, SeekOrigin origin) { - long newPosn = -1; + long newPosn; // Lock down the file stream while we do this. lock (_lock) @@ -763,13 +836,16 @@ public override long Seek(long offset, SeekOrigin origin) CheckSessionIsOpen(); if (!CanSeek) + { throw new NotSupportedException("Seek is not supported."); + } // Don't do anything if the position won't be moving. if (origin == SeekOrigin.Begin && offset == _position) { return offset; } + if (origin == SeekOrigin.Current && offset == 0) { return _position; @@ -822,11 +898,11 @@ public override long Seek(long offset, SeekOrigin origin) newPosn = _position + offset; break; case SeekOrigin.End: - var attributes = _session.RequestFStat(_handle, false); + var attributes = _session.RequestFStat(_handle, nullOnError: false); newPosn = attributes.Size + offset; break; default: - throw new ArgumentException(message: "Invalid seek origin.", paramName: "origin"); + throw new ArgumentException("Invalid seek origin.", nameof(origin)); } if (newPosn < 0) @@ -863,7 +939,9 @@ public override long Seek(long offset, SeekOrigin origin) public override void SetLength(long value) { if (value < 0) - throw new ArgumentOutOfRangeException("value"); + { + throw new ArgumentOutOfRangeException(nameof(value)); + } // Lock down the file stream while we do this. lock (_lock) @@ -871,7 +949,9 @@ public override void SetLength(long value) CheckSessionIsOpen(); if (!CanSeek) + { throw new NotSupportedException("Seek is not supported."); + } if (_bufferOwnedByWrite) { @@ -882,7 +962,7 @@ public override void SetLength(long value) SetupWrite(); } - var attributes = _session.RequestFStat(_handle, false); + var attributes = _session.RequestFStat(_handle, nullOnError: false); attributes.Size = value; _session.RequestFSetStat(_handle, attributes); @@ -908,13 +988,24 @@ public override void SetLength(long value) public override void Write(byte[] buffer, int offset, int count) { if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset < 0) - throw new ArgumentOutOfRangeException("offset"); + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if (count < 0) - throw new ArgumentOutOfRangeException("count"); + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + if ((buffer.Length - offset) < count) + { throw new ArgumentException("Invalid array range."); + } // Lock down the file stream while we do this. lock (_lock) @@ -933,6 +1024,7 @@ public override void Write(byte[] buffer, int offset, int count) { // flush write buffer, and mark it empty FlushWriteBuffer(); + // we can now write or buffer the full buffer size tempLen = _writeBufferSize; } @@ -946,7 +1038,7 @@ public override void Write(byte[] buffer, int offset, int count) // Can we short-cut the internal buffer? if (_bufferPosition == 0 && tempLen == _writeBufferSize) { - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { _session.RequestWrite(_handle, (ulong) _position, buffer, offset, tempLen, wait); } @@ -968,7 +1060,7 @@ public override void Write(byte[] buffer, int offset, int count) // rather than waiting for the next call to this method. if (_bufferPosition >= _writeBufferSize) { - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { _session.RequestWrite(_handle, (ulong) (_position - _bufferPosition), GetOrCreateWriteBuffer(), 0, _bufferPosition, wait); } @@ -978,7 +1070,6 @@ public override void Write(byte[] buffer, int offset, int count) } } - /// /// Asynchronously writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written. /// @@ -996,13 +1087,24 @@ public override void Write(byte[] buffer, int offset, int count) public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (buffer == null) - throw new ArgumentNullException("buffer"); + { + throw new ArgumentNullException(nameof(buffer)); + } + if (offset < 0) - throw new ArgumentOutOfRangeException("offset"); + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if (count < 0) - throw new ArgumentOutOfRangeException("count"); + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + if ((buffer.Length - offset) < count) + { throw new ArgumentException("Invalid array range."); + } CheckSessionIsOpen(); @@ -1018,6 +1120,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc { // flush write buffer, and mark it empty await FlushWriteBufferAsync(cancellationToken).ConfigureAwait(false); + // we can now write or buffer the full buffer size tempLen = _writeBufferSize; } @@ -1077,7 +1180,7 @@ public override void WriteByte(byte value) // Flush the current buffer if it is full. if (_bufferPosition >= _writeBufferSize) { - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { _session.RequestWrite(_handle, (ulong) (_position - _bufferPosition), writeBuffer, 0, _bufferPosition, wait); } @@ -1135,15 +1238,13 @@ protected override void Dispose(bool disposing) private byte[] GetOrCreateReadBuffer() { - if (_readBuffer == null) - _readBuffer = new byte[_readBufferSize]; + _readBuffer ??= new byte[_readBufferSize]; return _readBuffer; } private byte[] GetOrCreateWriteBuffer() { - if (_writeBuffer == null) - _writeBuffer = new byte[_writeBufferSize]; + _writeBuffer ??= new byte[_writeBufferSize]; return _writeBuffer; } @@ -1163,7 +1264,7 @@ private void FlushWriteBuffer() { if (_bufferPosition > 0) { - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { _session.RequestWrite(_handle, (ulong) (_position - _bufferPosition), _writeBuffer, 0, _bufferPosition, wait); } @@ -1176,7 +1277,7 @@ private async Task FlushWriteBufferAsync(CancellationToken cancellationToken) { if (_bufferPosition > 0) { - await _session.RequestWriteAsync(_handle, (ulong)(_position - _bufferPosition), _writeBuffer, 0, _bufferPosition, cancellationToken); + await _session.RequestWriteAsync(_handle, (ulong)(_position - _bufferPosition), _writeBuffer, 0, _bufferPosition, cancellationToken).ConfigureAwait(false); _bufferPosition = 0; } } @@ -1187,7 +1288,9 @@ private async Task FlushWriteBufferAsync(CancellationToken cancellationToken) private void SetupRead() { if (!CanRead) + { throw new NotSupportedException("Read not supported."); + } if (_bufferOwnedByWrite) { @@ -1201,8 +1304,10 @@ private void SetupRead() /// private void SetupWrite() { - if ((!CanWrite)) + if (!CanWrite) + { throw new NotSupportedException("Write not supported."); + } if (!_bufferOwnedByWrite) { @@ -1214,9 +1319,14 @@ private void SetupWrite() private void CheckSessionIsOpen() { if (_session == null) + { throw new ObjectDisposedException(GetType().FullName); + } + if (!_session.IsOpen) + { throw new ObjectDisposedException(GetType().FullName, "Cannot access a closed SFTP session."); + } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs index 2b791e54c..b69c05b27 100644 --- a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; + using Renci.SshNet.Common; namespace Renci.SshNet.Sftp @@ -13,16 +14,15 @@ public class SftpListDirectoryAsyncResult : AsyncResult> /// Gets the number of files read so far. /// public int FilesRead { get; private set; } - + /// /// Initializes a new instance of the class. /// /// The async callback. /// The state. - public SftpListDirectoryAsyncResult(AsyncCallback asyncCallback, Object state) + public SftpListDirectoryAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) { - } /// diff --git a/src/Renci.SshNet/Sftp/SftpMessage.cs b/src/Renci.SshNet/Sftp/SftpMessage.cs index 8f131fa79..5ecb69bc8 100644 --- a/src/Renci.SshNet/Sftp/SftpMessage.cs +++ b/src/Renci.SshNet/Sftp/SftpMessage.cs @@ -1,6 +1,7 @@ -using System.IO; +using System.Globalization; +using System.IO; + using Renci.SshNet.Common; -using System.Globalization; namespace Renci.SshNet.Sftp { @@ -44,7 +45,7 @@ protected override void WriteBytes(SshDataStream stream) var startPosition = stream.Position; // skip 4 bytes for the length of the SFTP message data - stream.Seek(sizeOfDataLengthBytes, SeekOrigin.Current); + _ = stream.Seek(sizeOfDataLengthBytes, SeekOrigin.Current); // write the SFTP message data to the stream base.WriteBytes(stream); diff --git a/src/Renci.SshNet/Sftp/SftpMessageTypes.cs b/src/Renci.SshNet/Sftp/SftpMessageTypes.cs index d74fc6ccd..25ea00eac 100644 --- a/src/Renci.SshNet/Sftp/SftpMessageTypes.cs +++ b/src/Renci.SshNet/Sftp/SftpMessageTypes.cs @@ -1,130 +1,155 @@ - -namespace Renci.SshNet.Sftp +namespace Renci.SshNet.Sftp { internal enum SftpMessageTypes : byte { /// - /// SSH_FXP_INIT + /// SSH_FXP_INIT. /// Init = 1, + /// - /// SSH_FXP_VERSION + /// SSH_FXP_VERSION. /// Version = 2, + /// - /// SSH_FXP_OPEN + /// SSH_FXP_OPEN. /// Open = 3, + /// - /// SSH_FXP_CLOSE + /// SSH_FXP_CLOSE. /// Close = 4, + /// - /// SSH_FXP_READ + /// SSH_FXP_READ. /// Read = 5, + /// - /// SSH_FXP_WRITE + /// SSH_FXP_WRITE. /// Write = 6, + /// - /// SSH_FXP_LSTAT + /// SSH_FXP_LSTAT. /// LStat = 7, + /// - /// SSH_FXP_FSTAT + /// SSH_FXP_FSTAT. /// FStat = 8, + /// - /// SSH_FXP_SETSTAT + /// SSH_FXP_SETSTAT. /// SetStat = 9, + /// - /// SSH_FXP_FSETSTAT + /// SSH_FXP_FSETSTAT. /// FSetStat = 10, + /// - /// SSH_FXP_OPENDIR + /// SSH_FXP_OPENDIR. /// OpenDir = 11, + /// - /// SSH_FXP_READDIR + /// SSH_FXP_READDIR. /// ReadDir = 12, + /// - /// SSH_FXP_REMOVE + /// SSH_FXP_REMOVE. /// Remove = 13, + /// - /// SSH_FXP_MKDIR + /// SSH_FXP_MKDIR. /// MkDir = 14, + /// - /// SSH_FXP_RMDIR + /// SSH_FXP_RMDIR. /// RmDir = 15, + /// - /// SSH_FXP_REALPATH + /// SSH_FXP_REALPATH. /// RealPath = 16, + /// - /// SSH_FXP_STAT + /// SSH_FXP_STAT. /// Stat = 17, + /// - /// SSH_FXP_RENAME + /// SSH_FXP_RENAME. /// Rename = 18, + /// - /// SSH_FXP_READLINK + /// SSH_FXP_READLINK. /// ReadLink = 19, + /// - /// SSH_FXP_SYMLINK + /// SSH_FXP_SYMLINK. /// SymLink = 20, + /// - /// SSH_FXP_LINK + /// SSH_FXP_LINK. /// Link = 21, + /// - /// SSH_FXP_BLOCK + /// SSH_FXP_BLOCK. /// Block = 22, + /// - /// SSH_FXP_UNBLOCK + /// SSH_FXP_UNBLOCK. /// Unblock = 23, /// - /// SSH_FXP_STATUS + /// SSH_FXP_STATUS. /// Status = 101, + /// - /// SSH_FXP_HANDLE + /// SSH_FXP_HANDLE. /// Handle = 102, + /// - /// SSH_FXP_DATA + /// SSH_FXP_DATA. /// Data = 103, + /// - /// SSH_FXP_NAME + /// SSH_FXP_NAME. /// Name = 104, + /// - /// SSH_FXP_ATTRS + /// SSH_FXP_ATTRS. /// Attrs = 105, /// - /// SSH_FXP_EXTENDED + /// SSH_FXP_EXTENDED. /// Extended = 200, + /// - /// SSH_FXP_EXTENDED_REPLY + /// SSH_FXP_EXTENDED_REPLY. /// ExtendedReply = 201 - } } diff --git a/src/Renci.SshNet/Sftp/SftpOpenAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpOpenAsyncResult.cs index b19de7e79..a239172e4 100644 --- a/src/Renci.SshNet/Sftp/SftpOpenAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpOpenAsyncResult.cs @@ -1,11 +1,13 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Sftp { - internal class SftpOpenAsyncResult : AsyncResult + internal sealed class SftpOpenAsyncResult : AsyncResult { - public SftpOpenAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) + public SftpOpenAsyncResult(AsyncCallback asyncCallback, object state) + : base(asyncCallback, state) { } } diff --git a/src/Renci.SshNet/Sftp/SftpReadAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpReadAsyncResult.cs index 65911d222..9814f0e8f 100644 --- a/src/Renci.SshNet/Sftp/SftpReadAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpReadAsyncResult.cs @@ -1,11 +1,13 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Sftp { - internal class SftpReadAsyncResult : AsyncResult + internal sealed class SftpReadAsyncResult : AsyncResult { - public SftpReadAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) + public SftpReadAsyncResult(AsyncCallback asyncCallback, object state) + : base(asyncCallback, state) { } } diff --git a/src/Renci.SshNet/Sftp/SftpRealPathAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpRealPathAsyncResult.cs index e1f1fbf95..ab8600320 100644 --- a/src/Renci.SshNet/Sftp/SftpRealPathAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpRealPathAsyncResult.cs @@ -1,11 +1,13 @@ -using Renci.SshNet.Common; -using System; +using System; + +using Renci.SshNet.Common; namespace Renci.SshNet.Sftp { - internal class SftpRealPathAsyncResult : AsyncResult + internal sealed class SftpRealPathAsyncResult : AsyncResult { - public SftpRealPathAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) + public SftpRealPathAsyncResult(AsyncCallback asyncCallback, object state) + : base(asyncCallback, state) { } } diff --git a/src/Renci.SshNet/Sftp/SftpResponseFactory.cs b/src/Renci.SshNet/Sftp/SftpResponseFactory.cs index ad6b22913..0edcfcf7c 100644 --- a/src/Renci.SshNet/Sftp/SftpResponseFactory.cs +++ b/src/Renci.SshNet/Sftp/SftpResponseFactory.cs @@ -1,7 +1,8 @@ using System; +using System.Globalization; using System.Text; + using Renci.SshNet.Sftp.Responses; -using System.Globalization; namespace Renci.SshNet.Sftp { diff --git a/src/Renci.SshNet/Sftp/SftpSession.cs b/src/Renci.SshNet/Sftp/SftpSession.cs index dd38bd36e..7bba929ed 100644 --- a/src/Renci.SshNet/Sftp/SftpSession.cs +++ b/src/Renci.SshNet/Sftp/SftpSession.cs @@ -1,12 +1,13 @@ using System; +using System.Collections.Generic; +using System.Globalization; using System.Text; using System.Threading; +using System.Threading.Tasks; + using Renci.SshNet.Common; -using System.Collections.Generic; -using System.Globalization; -using Renci.SshNet.Sftp.Responses; using Renci.SshNet.Sftp.Requests; -using System.Threading.Tasks; +using Renci.SshNet.Sftp.Responses; namespace Renci.SshNet.Sftp { @@ -17,9 +18,8 @@ internal class SftpSession : SubsystemSession, ISftpSession private readonly Dictionary _requests = new Dictionary(); private readonly ISftpResponseFactory _sftpResponseFactory; - //FIXME: obtain from SftpClient! private readonly List _data = new List(32 * 1024); - private EventWaitHandle _sftpVersionConfirmed = new AutoResetEvent(false); + private EventWaitHandle _sftpVersionConfirmed = new AutoResetEvent(initialState: false); private IDictionary _supportedExtensions; /// @@ -56,6 +56,13 @@ public uint NextRequestId } } + /// + /// Initializes a new instance of the class. + /// + /// The SSH session. + /// The operation timeout. + /// The character encoding to use. + /// The factory to create SFTP responses. public SftpSession(ISession session, int operationTimeout, Encoding encoding, ISftpResponseFactory sftpResponseFactory) : base(session, "sftp", operationTimeout) { @@ -95,7 +102,7 @@ public string GetCanonicalPath(string path) var canonizedPath = string.Empty; - var realPathFiles = RequestRealPath(fullPath, true); + var realPathFiles = RequestRealPath(fullPath, nullOnError: true); if (realPathFiles != null) { @@ -103,23 +110,29 @@ public string GetCanonicalPath(string path) } if (!string.IsNullOrEmpty(canonizedPath)) + { return canonizedPath; + } - // Check for special cases + // Check for special cases if (fullPath.EndsWith("/.", StringComparison.OrdinalIgnoreCase) || fullPath.EndsWith("/..", StringComparison.OrdinalIgnoreCase) || fullPath.Equals("/", StringComparison.OrdinalIgnoreCase) || fullPath.IndexOf('/') < 0) + { return fullPath; + } var pathParts = fullPath.Split('/'); var partialFullPath = string.Join("/", pathParts, 0, pathParts.Length - 1); if (string.IsNullOrEmpty(partialFullPath)) + { partialFullPath = "/"; + } - realPathFiles = RequestRealPath(partialFullPath, true); + realPathFiles = RequestRealPath(partialFullPath, nullOnError: true); if (realPathFiles != null) { @@ -133,7 +146,10 @@ public string GetCanonicalPath(string path) var slash = string.Empty; if (canonizedPath[canonizedPath.Length - 1] != '/') + { slash = "/"; + } + return string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", canonizedPath, slash, pathParts[pathParts.Length - 1]); } @@ -142,30 +158,36 @@ public async Task GetCanonicalPathAsync(string path, CancellationToken c var fullPath = GetFullRemotePath(path); var canonizedPath = string.Empty; - var realPathFiles = await RequestRealPathAsync(fullPath, true, cancellationToken).ConfigureAwait(false); + var realPathFiles = await RequestRealPathAsync(fullPath, nullOnError: true, cancellationToken).ConfigureAwait(false); if (realPathFiles != null) { canonizedPath = realPathFiles[0].Key; } if (!string.IsNullOrEmpty(canonizedPath)) + { return canonizedPath; + } - // Check for special cases + // Check for special cases if (fullPath.EndsWith("/.", StringComparison.Ordinal) || fullPath.EndsWith("/..", StringComparison.Ordinal) || fullPath.Equals("/", StringComparison.Ordinal) || fullPath.IndexOf('/') < 0) + { return fullPath; + } var pathParts = fullPath.Split('/'); var partialFullPath = string.Join("/", pathParts, 0, pathParts.Length - 1); if (string.IsNullOrEmpty(partialFullPath)) + { partialFullPath = "/"; + } - realPathFiles = await RequestRealPathAsync(partialFullPath, true, cancellationToken).ConfigureAwait(false); + realPathFiles = await RequestRealPathAsync(partialFullPath, nullOnError: true, cancellationToken).ConfigureAwait(false); if (realPathFiles != null) { @@ -179,7 +201,10 @@ public async Task GetCanonicalPathAsync(string path, CancellationToken c var slash = string.Empty; if (canonizedPath[canonizedPath.Length - 1] != '/') + { slash = "/"; + } + return canonizedPath + slash + pathParts[pathParts.Length - 1]; } @@ -212,12 +237,12 @@ protected override void OnChannelOpen() WaitOnHandle(_sftpVersionConfirmed, OperationTimeout); - if (ProtocolVersion > MaximumSupportedVersion || ProtocolVersion < MinimumSupportedVersion) + if (ProtocolVersion is > MaximumSupportedVersion or < MinimumSupportedVersion) { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Server SFTP version {0} is not supported.", ProtocolVersion)); } - // Resolve current directory + // Resolve current directory WorkingDirectory = RequestRealPath(".")[0].Key; } @@ -339,18 +364,18 @@ private bool TryLoadSftpMessage(byte[] packetData, int offset, int count) { // Create SFTP message var response = _sftpResponseFactory.Create(ProtocolVersion, packetData[offset], Encoding); + // Load message data into it response.Load(packetData, offset + 1, count - 1); try { - var versionResponse = response as SftpVersionResponse; - if (versionResponse != null) + if (response is SftpVersionResponse versionResponse) { ProtocolVersion = versionResponse.Version; _supportedExtensions = versionResponse.Extentions; - _sftpVersionConfirmed.Set(); + _ = _sftpVersionConfirmed.Set(); } else { @@ -391,10 +416,8 @@ private void SendRequest(SftpRequest request) SendMessage(request); } - #region SFTP API functions - /// - /// Performs SSH_FXP_OPEN request + /// Performs SSH_FXP_OPEN request. /// /// The path. /// The flags. @@ -405,19 +428,23 @@ public byte[] RequestOpen(string path, Flags flags, bool nullOnError = false) byte[] handle = null; SshException exception = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpOpenRequest(ProtocolVersion, NextRequestId, path, Encoding, flags, - response => - { - handle = response.Handle; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpOpenRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + flags, + response => + { + handle = response.Handle; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -436,20 +463,24 @@ public async Task RequestOpenAsync(string path, Flags flags, Cancellatio { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - SendRequest(new SftpOpenRequest(ProtocolVersion, NextRequestId, path, Encoding, flags, - response => tcs.TrySetResult(response.Handle), - response => tcs.TrySetException(GetSftpException(response)))); + SendRequest(new SftpOpenRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + flags, + response => tcs.TrySetResult(response.Handle), + response => tcs.TrySetException(GetSftpException(response)))); return await tcs.Task.ConfigureAwait(false); } } /// - /// Performs SSH_FXP_OPEN request + /// Performs SSH_FXP_OPEN request. /// /// The path. /// The flags. @@ -462,15 +493,19 @@ public SftpOpenAsyncResult BeginOpen(string path, Flags flags, AsyncCallback cal { var asyncResult = new SftpOpenAsyncResult(callback, state); - var request = new SftpOpenRequest(ProtocolVersion, NextRequestId, path, Encoding, flags, - response => - { - asyncResult.SetAsCompleted(response.Handle, false); - }, - response => - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - }); + var request = new SftpOpenRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + flags, + response => + { + asyncResult.SetAsCompleted(response.Handle, completedSynchronously: false); + }, + response => + { + asyncResult.SetAsCompleted(GetSftpException(response), completedSynchronously: false); + }); SendRequest(request); @@ -492,13 +527,19 @@ public SftpOpenAsyncResult BeginOpen(string path, Flags flags, AsyncCallback cal public byte[] EndOpen(SftpOpenAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndOpen has already been called."); + } if (asyncResult.IsCompleted) + { return asyncResult.EndInvoke(); + } using (var waitHandle = asyncResult.AsyncWaitHandle) { @@ -515,14 +556,16 @@ public void RequestClose(byte[] handle) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpCloseRequest(ProtocolVersion, NextRequestId, handle, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpCloseRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -537,26 +580,29 @@ public void RequestClose(byte[] handle) public async Task RequestCloseAsync(byte[] handle, CancellationToken cancellationToken) { - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - SendRequest(new SftpCloseRequest(ProtocolVersion, NextRequestId, handle, - response => - { - if (response.StatusCode == StatusCodes.Ok) - { - tcs.TrySetResult(true); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + SendRequest(new SftpCloseRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + if (response.StatusCode == StatusCodes.Ok) + { + _ = tcs.TrySetResult(true); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); // Only check for cancellation after the SftpCloseRequest was sent cancellationToken.ThrowIfCancellationRequested(); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - await tcs.Task.ConfigureAwait(false); + _ = await tcs.Task.ConfigureAwait(false); } } @@ -573,11 +619,13 @@ public SftpCloseAsyncResult BeginClose(byte[] handle, AsyncCallback callback, ob { var asyncResult = new SftpCloseAsyncResult(callback, state); - var request = new SftpCloseRequest(ProtocolVersion, NextRequestId, handle, - response => - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - }); + var request = new SftpCloseRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + asyncResult.SetAsCompleted(GetSftpException(response), false); + }); SendRequest(request); return asyncResult; @@ -591,10 +639,14 @@ public SftpCloseAsyncResult BeginClose(byte[] handle, AsyncCallback callback, ob public void EndClose(SftpCloseAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndClose has already been called."); + } if (asyncResult.IsCompleted) { @@ -625,22 +677,26 @@ public SftpReadAsyncResult BeginRead(byte[] handle, ulong offset, uint length, A { var asyncResult = new SftpReadAsyncResult(callback, state); - var request = new SftpReadRequest(ProtocolVersion, NextRequestId, handle, offset, length, - response => - { - asyncResult.SetAsCompleted(response.Data, false); - }, - response => - { - if (response.StatusCode != StatusCodes.Eof) - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - } - else - { - asyncResult.SetAsCompleted(Array.Empty, false); - } - }); + var request = new SftpReadRequest(ProtocolVersion, + NextRequestId, + handle, + offset, + length, + response => + { + asyncResult.SetAsCompleted(response.Data, completedSynchronously: false); + }, + response => + { + if (response.StatusCode != StatusCodes.Eof) + { + asyncResult.SetAsCompleted(GetSftpException(response), completedSynchronously: false); + } + else + { + asyncResult.SetAsCompleted(Array.Empty, completedSynchronously: false); + } + }); SendRequest(request); return asyncResult; @@ -661,13 +717,19 @@ public SftpReadAsyncResult BeginRead(byte[] handle, ulong offset, uint length, A public byte[] EndRead(SftpReadAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndRead has already been called."); + } if (asyncResult.IsCompleted) + { return asyncResult.EndInvoke(); + } using (var waitHandle = asyncResult.AsyncWaitHandle) { @@ -689,26 +751,31 @@ public byte[] RequestRead(byte[] handle, ulong offset, uint length) byte[] data = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpReadRequest(ProtocolVersion, NextRequestId, handle, offset, length, - response => - { - data = response.Data; - wait.Set(); - }, - response => - { - if (response.StatusCode != StatusCodes.Eof) - { - exception = GetSftpException(response); - } - else - { - data = Array.Empty; - } - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpReadRequest(ProtocolVersion, + NextRequestId, + handle, + offset, + length, + response => + { + data = response.Data; + _ = wait.Set(); + }, + response => + { + if (response.StatusCode != StatusCodes.Eof) + { + exception = GetSftpException(response); + } + else + { + data = Array.Empty; + } + + _ = wait.Set(); + }); SendRequest(request); @@ -727,23 +794,27 @@ public async Task RequestReadAsync(byte[] handle, ulong offset, uint len { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) - { - SendRequest(new SftpReadRequest(ProtocolVersion, NextRequestId, handle, offset, length, - response => tcs.TrySetResult(response.Data), - response => - { - if (response.StatusCode == StatusCodes.Eof) - { - tcs.TrySetResult(Array.Empty); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) + { + SendRequest(new SftpReadRequest(ProtocolVersion, + NextRequestId, + handle, + offset, + length, + response => tcs.TrySetResult(response.Data), + response => + { + if (response.StatusCode == StatusCodes.Eof) + { + _ = tcs.TrySetResult(Array.Empty); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); return await tcs.Task.ConfigureAwait(false); } @@ -769,23 +840,30 @@ public void RequestWrite(byte[] handle, { SshException exception = null; - var request = new SftpWriteRequest(ProtocolVersion, NextRequestId, handle, serverOffset, data, offset, - length, response => - { - if (writeCompleted != null) - { - writeCompleted(response); - } - - exception = GetSftpException(response); - if (wait != null) - wait.Set(); - }); + var request = new SftpWriteRequest(ProtocolVersion, + NextRequestId, + handle, + serverOffset, + data, + offset, + length, + response => + { + writeCompleted?.Invoke(response); + + exception = GetSftpException(response); + if (wait != null) + { + _ = wait.Set(); + } + }); SendRequest(request); if (wait != null) + { WaitOnHandle(wait, OperationTimeout); + } if (exception != null) { @@ -797,24 +875,30 @@ public async Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] da { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) - { - SendRequest(new SftpWriteRequest(ProtocolVersion, NextRequestId, handle, serverOffset, data, offset, length, - response => - { - if (response.StatusCode == StatusCodes.Ok) - { - tcs.TrySetResult(true); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); - - await tcs.Task.ConfigureAwait(false); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) + { + SendRequest(new SftpWriteRequest(ProtocolVersion, + NextRequestId, + handle, + serverOffset, + data, + offset, + length, + response => + { + if (response.StatusCode == StatusCodes.Ok) + { + _ = tcs.TrySetResult(true); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); + + _ = await tcs.Task.ConfigureAwait(false); } } @@ -823,26 +907,29 @@ public async Task RequestWriteAsync(byte[] handle, ulong serverOffset, byte[] da /// /// The path. /// - /// File attributes + /// File attributes. /// public SftpFileAttributes RequestLStat(string path) { SshException exception = null; SftpFileAttributes attributes = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpLStatRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - attributes = response.Attributes; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpLStatRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + attributes = response.Attributes; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -870,15 +957,18 @@ public SFtpStatAsyncResult BeginLStat(string path, AsyncCallback callback, objec { var asyncResult = new SFtpStatAsyncResult(callback, state); - var request = new SftpLStatRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - asyncResult.SetAsCompleted(response.Attributes, false); - }, - response => - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - }); + var request = new SftpLStatRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + asyncResult.SetAsCompleted(response.Attributes, completedSynchronously: false); + }, + response => + { + asyncResult.SetAsCompleted(GetSftpException(response), completedSynchronously: false); + }); SendRequest(request); return asyncResult; @@ -895,13 +985,19 @@ public SFtpStatAsyncResult BeginLStat(string path, AsyncCallback callback, objec public SftpFileAttributes EndLStat(SFtpStatAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndLStat has already been called."); + } if (asyncResult.IsCompleted) + { return asyncResult.EndInvoke(); + } using (var waitHandle = asyncResult.AsyncWaitHandle) { @@ -916,26 +1012,28 @@ public SftpFileAttributes EndLStat(SFtpStatAsyncResult asyncResult) /// The handle. /// if set to true returns null instead of throwing an exception. /// - /// File attributes + /// File attributes. /// public SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError) { SshException exception = null; SftpFileAttributes attributes = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpFStatRequest(ProtocolVersion, NextRequestId, handle, - response => - { - attributes = response.Attributes; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpFStatRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + attributes = response.Attributes; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -954,13 +1052,15 @@ public async Task RequestFStatAsync(byte[] handle, Cancellat { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - SendRequest(new SftpFStatRequest(ProtocolVersion, NextRequestId, handle, - response => tcs.TrySetResult(response.Attributes), - response => tcs.TrySetException(GetSftpException(response)))); + SendRequest(new SftpFStatRequest(ProtocolVersion, + NextRequestId, + handle, + response => tcs.TrySetResult(response.Attributes), + response => tcs.TrySetException(GetSftpException(response)))); return await tcs.Task.ConfigureAwait(false); } @@ -975,14 +1075,18 @@ public void RequestSetStat(string path, SftpFileAttributes attributes) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpSetStatRequest(ProtocolVersion, NextRequestId, path, Encoding, attributes, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpSetStatRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + attributes, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1004,14 +1108,17 @@ public void RequestFSetStat(byte[] handle, SftpFileAttributes attributes) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpFSetStatRequest(ProtocolVersion, NextRequestId, handle, attributes, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpFSetStatRequest(ProtocolVersion, + NextRequestId, + handle, + attributes, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1025,7 +1132,7 @@ public void RequestFSetStat(byte[] handle, SftpFileAttributes attributes) } /// - /// Performs SSH_FXP_OPENDIR request + /// Performs SSH_FXP_OPENDIR request. /// /// The path. /// if set to true returns null instead of throwing an exception. @@ -1036,19 +1143,22 @@ public byte[] RequestOpenDir(string path, bool nullOnError = false) byte[] handle = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpOpenDirRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - handle = response.Handle; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpOpenDirRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + handle = response.Handle; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1067,20 +1177,23 @@ public async Task RequestOpenDirAsync(string path, CancellationToken can { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - SendRequest(new SftpOpenDirRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => tcs.TrySetResult(response.Handle), - response => tcs.TrySetException(GetSftpException(response)))); + SendRequest(new SftpOpenDirRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => tcs.TrySetResult(response.Handle), + response => tcs.TrySetException(GetSftpException(response)))); return await tcs.Task.ConfigureAwait(false); } } /// - /// Performs SSH_FXP_READDIR request + /// Performs SSH_FXP_READDIR request. /// /// The handle. /// @@ -1090,22 +1203,25 @@ public KeyValuePair[] RequestReadDir(byte[] handle) KeyValuePair[] result = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpReadDirRequest(ProtocolVersion, NextRequestId, handle, - response => - { - result = response.Files; - wait.Set(); - }, - response => - { - if (response.StatusCode != StatusCodes.Eof) - { - exception = GetSftpException(response); - } - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpReadDirRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + result = response.Files; + _ = wait.Set(); + }, + response => + { + if (response.StatusCode != StatusCodes.Eof) + { + exception = GetSftpException(response); + } + + _ = wait.Set(); + }); SendRequest(request); @@ -1124,23 +1240,25 @@ public async Task[]> RequestReadDirAsyn { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource[]> tcs = new TaskCompletionSource[]>(TaskCreationOptions.RunContinuationsAsynchronously); - - using (cancellationToken.Register((s) => ((TaskCompletionSource[]>)s).TrySetCanceled(), tcs, false)) - { - SendRequest(new SftpReadDirRequest(ProtocolVersion, NextRequestId, handle, - response => tcs.TrySetResult(response.Files), - response => - { - if (response.StatusCode == StatusCodes.Eof) - { - tcs.TrySetResult(null); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); + var tcs = new TaskCompletionSource[]>(TaskCreationOptions.RunContinuationsAsynchronously); + + using (cancellationToken.Register((s) => ((TaskCompletionSource[]>) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) + { + SendRequest(new SftpReadDirRequest(ProtocolVersion, + NextRequestId, + handle, + response => tcs.TrySetResult(response.Files), + response => + { + if (response.StatusCode == StatusCodes.Eof) + { + _ = tcs.TrySetResult(null); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); return await tcs.Task.ConfigureAwait(false); } @@ -1154,14 +1272,17 @@ public void RequestRemove(string path) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpRemoveRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpRemoveRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1178,24 +1299,27 @@ public async Task RequestRemoveAsync(string path, CancellationToken cancellation { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - SendRequest(new SftpRemoveRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - if (response.StatusCode == StatusCodes.Ok) - { - tcs.TrySetResult(true); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); + SendRequest(new SftpRemoveRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + if (response.StatusCode == StatusCodes.Ok) + { + _ = tcs.TrySetResult(true); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); - await tcs.Task.ConfigureAwait(false); + _ = await tcs.Task.ConfigureAwait(false); } } @@ -1207,14 +1331,17 @@ public void RequestMkDir(string path) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpMkDirRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpMkDirRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1235,14 +1362,17 @@ public void RequestRmDir(string path) { SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpRmDirRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpRmDirRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1256,7 +1386,7 @@ public void RequestRmDir(string path) } /// - /// Performs SSH_FXP_REALPATH request + /// Performs SSH_FXP_REALPATH request. /// /// The path. /// if set to true returns null instead of throwing an exception. @@ -1269,19 +1399,22 @@ internal KeyValuePair[] RequestRealPath(string path, KeyValuePair[] result = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpRealPathRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - result = response.Files; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpRealPathRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + result = response.Files; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1300,23 +1433,26 @@ internal async Task[]> RequestRealPathA { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource[]> tcs = new TaskCompletionSource[]>(TaskCreationOptions.RunContinuationsAsynchronously); - - using (cancellationToken.Register((s) => ((TaskCompletionSource[]>)s).TrySetCanceled(), tcs, false)) - { - SendRequest(new SftpRealPathRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => tcs.TrySetResult(response.Files), - response => - { - if (nullOnError) - { - tcs.TrySetResult(null); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); + var tcs = new TaskCompletionSource[]>(TaskCreationOptions.RunContinuationsAsynchronously); + + using (cancellationToken.Register((s) => ((TaskCompletionSource[]>) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) + { + SendRequest(new SftpRealPathRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => tcs.TrySetResult(response.Files), + response => + { + if (nullOnError) + { + _ = tcs.TrySetResult(null); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); return await tcs.Task.ConfigureAwait(false); } @@ -1335,15 +1471,12 @@ public SftpRealPathAsyncResult BeginRealPath(string path, AsyncCallback callback { var asyncResult = new SftpRealPathAsyncResult(callback, state); - var request = new SftpRealPathRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - asyncResult.SetAsCompleted(response.Files[0].Key, false); - }, - response => - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - }); + var request = new SftpRealPathRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => asyncResult.SetAsCompleted(response.Files[0].Key, completedSynchronously: false), + response => asyncResult.SetAsCompleted(GetSftpException(response), completedSynchronously: false)); SendRequest(request); return asyncResult; @@ -1360,13 +1493,19 @@ public SftpRealPathAsyncResult BeginRealPath(string path, AsyncCallback callback public string EndRealPath(SftpRealPathAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndRealPath has already been called."); + } if (asyncResult.IsCompleted) + { return asyncResult.EndInvoke(); + } using (var waitHandle = asyncResult.AsyncWaitHandle) { @@ -1381,7 +1520,7 @@ public string EndRealPath(SftpRealPathAsyncResult asyncResult) /// The path. /// if set to true returns null instead of throwing an exception. /// - /// File attributes + /// File attributes. /// public SftpFileAttributes RequestStat(string path, bool nullOnError = false) { @@ -1389,19 +1528,22 @@ public SftpFileAttributes RequestStat(string path, bool nullOnError = false) SftpFileAttributes attributes = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpStatRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - attributes = response.Attributes; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpStatRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + attributes = response.Attributes; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1417,7 +1559,7 @@ public SftpFileAttributes RequestStat(string path, bool nullOnError = false) } /// - /// Performs SSH_FXP_STAT request + /// Performs SSH_FXP_STAT request. /// /// The path. /// The delegate that is executed when completes. @@ -1429,15 +1571,12 @@ public SFtpStatAsyncResult BeginStat(string path, AsyncCallback callback, object { var asyncResult = new SFtpStatAsyncResult(callback, state); - var request = new SftpStatRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - asyncResult.SetAsCompleted(response.Attributes, false); - }, - response => - { - asyncResult.SetAsCompleted(GetSftpException(response), false); - }); + var request = new SftpStatRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => asyncResult.SetAsCompleted(response.Attributes, completedSynchronously: false), + response => asyncResult.SetAsCompleted(GetSftpException(response), completedSynchronously: false)); SendRequest(request); return asyncResult; @@ -1454,13 +1593,19 @@ public SFtpStatAsyncResult BeginStat(string path, AsyncCallback callback, object public SftpFileAttributes EndStat(SFtpStatAsyncResult asyncResult) { if (asyncResult == null) - throw new ArgumentNullException("asyncResult"); + { + throw new ArgumentNullException(nameof(asyncResult)); + } if (asyncResult.EndInvokeCalled) + { throw new InvalidOperationException("EndStat has already been called."); + } if (asyncResult.IsCompleted) + { return asyncResult.EndInvoke(); + } using (var waitHandle = asyncResult.AsyncWaitHandle) { @@ -1483,14 +1628,18 @@ public void RequestRename(string oldPath, string newPath) SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpRenameRequest(ProtocolVersion, NextRequestId, oldPath, newPath, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpRenameRequest(ProtocolVersion, + NextRequestId, + oldPath, + newPath, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1507,24 +1656,28 @@ public async Task RequestRenameAsync(string oldPath, string newPath, Cancellatio { cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) - { - SendRequest(new SftpRenameRequest(ProtocolVersion, NextRequestId, oldPath, newPath, Encoding, - response => - { - if (response.StatusCode == StatusCodes.Ok) - { - tcs.TrySetResult(true); - } - else - { - tcs.TrySetException(GetSftpException(response)); - } - })); - - await tcs.Task.ConfigureAwait(false); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) + { + SendRequest(new SftpRenameRequest(ProtocolVersion, + NextRequestId, + oldPath, + newPath, + Encoding, + response => + { + if (response.StatusCode == StatusCodes.Ok) + { + _ = tcs.TrySetResult(true); + } + else + { + _ = tcs.TrySetException(GetSftpException(response)); + } + })); + + _ = await tcs.Task.ConfigureAwait(false); } } @@ -1545,19 +1698,22 @@ internal KeyValuePair[] RequestReadLink(string path, KeyValuePair[] result = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new SftpReadLinkRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - result = response.Files; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new SftpReadLinkRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + result = response.Files; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1586,14 +1742,18 @@ public void RequestSymLink(string linkpath, string targetpath) SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new SftpSymLinkRequest(ProtocolVersion, NextRequestId, linkpath, targetpath, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new SftpSymLinkRequest(ProtocolVersion, + NextRequestId, + linkpath, + targetpath, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); SendRequest(request); @@ -1606,10 +1766,6 @@ public void RequestSymLink(string linkpath, string targetpath) } } - #endregion - - #region SFTP Extended API functions - /// /// Performs posix-rename@openssh.com extended request. /// @@ -1624,17 +1780,23 @@ public void RequestPosixRename(string oldPath, string newPath) SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new PosixRenameRequest(ProtocolVersion, NextRequestId, oldPath, newPath, Encoding, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new PosixRenameRequest(ProtocolVersion, + NextRequestId, + oldPath, + newPath, + Encoding, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); if (!_supportedExtensions.ContainsKey(request.Name)) + { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + } SendRequest(request); @@ -1652,7 +1814,9 @@ public void RequestPosixRename(string oldPath, string newPath) /// /// The path. /// if set to true [null on error]. - /// + /// + /// A for the specified path. + /// public SftpFileSytemInformation RequestStatVfs(string path, bool nullOnError = false) { if (ProtocolVersion < 3) @@ -1664,22 +1828,27 @@ public SftpFileSytemInformation RequestStatVfs(string path, bool nullOnError = f SftpFileSytemInformation information = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new StatVfsRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => - { - information = response.GetReply().Information; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new StatVfsRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => + { + information = response.GetReply().Information; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); if (!_supportedExtensions.ContainsKey(request.Name)) + { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + } SendRequest(request); @@ -1703,13 +1872,16 @@ public async Task RequestStatVfsAsync(string path, Can cancellationToken.ThrowIfCancellationRequested(); - TaskCompletionSource tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - using (cancellationToken.Register((s) => ((TaskCompletionSource)s).TrySetCanceled(), tcs, false)) + using (cancellationToken.Register((s) => ((TaskCompletionSource) s).TrySetCanceled(), tcs, useSynchronizationContext: false)) { - SendRequest(new StatVfsRequest(ProtocolVersion, NextRequestId, path, Encoding, - response => tcs.TrySetResult(response.GetReply().Information), - response => tcs.TrySetException(GetSftpException(response)))); + SendRequest(new StatVfsRequest(ProtocolVersion, + NextRequestId, + path, + Encoding, + response => tcs.TrySetResult(response.GetReply().Information), + response => tcs.TrySetException(GetSftpException(response)))); return await tcs.Task.ConfigureAwait(false); } @@ -1720,8 +1892,10 @@ public async Task RequestStatVfsAsync(string path, Can /// /// The file handle. /// if set to true [null on error]. - /// - /// + /// + /// A for the specified path. + /// + /// This operation is not supported for the current SFTP protocol version. internal SftpFileSytemInformation RequestFStatVfs(byte[] handle, bool nullOnError = false) { if (ProtocolVersion < 3) @@ -1733,22 +1907,26 @@ internal SftpFileSytemInformation RequestFStatVfs(byte[] handle, bool nullOnErro SftpFileSytemInformation information = null; - using (var wait = new AutoResetEvent(false)) - { - var request = new FStatVfsRequest(ProtocolVersion, NextRequestId, handle, - response => - { - information = response.GetReply().Information; - wait.Set(); - }, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + using (var wait = new AutoResetEvent(initialState: false)) + { + var request = new FStatVfsRequest(ProtocolVersion, + NextRequestId, + handle, + response => + { + information = response.GetReply().Information; + _ = wait.Set(); + }, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); if (!_supportedExtensions.ContainsKey(request.Name)) + { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + } SendRequest(request); @@ -1777,17 +1955,22 @@ internal void HardLink(string oldPath, string newPath) SshException exception = null; - using (var wait = new AutoResetEvent(false)) + using (var wait = new AutoResetEvent(initialState: false)) { - var request = new HardLinkRequest(ProtocolVersion, NextRequestId, oldPath, newPath, - response => - { - exception = GetSftpException(response); - wait.Set(); - }); + var request = new HardLinkRequest(ProtocolVersion, + NextRequestId, + oldPath, + newPath, + response => + { + exception = GetSftpException(response); + _ = wait.Set(); + }); if (!_supportedExtensions.ContainsKey(request.Name)) + { throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + } SendRequest(request); @@ -1800,8 +1983,6 @@ internal void HardLink(string oldPath, string newPath) } } - #endregion - /// /// Calculates the optimal size of the buffer to read data from the channel. /// @@ -1815,7 +1996,7 @@ public uint CalculateOptimalReadLength(uint bufferSize) // bytes 1 to 4: packet length // byte 5: message type // bytes 6 to 9: response id - // bytes 10 to 13: length of payload‏ + // bytes 10 to 13: length of payload // // WinSCP uses a payload length of 32755 bytes // @@ -1851,8 +2032,10 @@ public uint CalculateOptimalWriteLength(uint bufferSize, byte[] handle) // 14-21: offset // 22-25: data length - // Putty uses data length of 4096 bytes - // WinSCP uses data length of 32739 bytes (total 32768 bytes; 32739 + 25 + 4 bytes for handle) + /* + * Putty uses data length of 4096 bytes + * WinSCP uses data length of 32739 bytes (total 32768 bytes; 32739 + 25 + 4 bytes for handle) + */ var lengthOfNonDataProtocolFields = 25u + (uint)handle.Length; var maximumPacketSize = Channel.RemotePacketSize; @@ -1879,15 +2062,17 @@ private void HandleResponse(SftpResponse response) SftpRequest request; lock (_requests) { - _requests.TryGetValue(response.ResponseId, out request); + _ = _requests.TryGetValue(response.ResponseId, out request); if (request != null) { - _requests.Remove(response.ResponseId); + _ = _requests.Remove(response.ResponseId); } } if (request == null) + { throw new InvalidOperationException("Invalid response."); + } request.Complete(response); } diff --git a/src/Renci.SshNet/Sftp/SftpSynchronizeDirectoriesAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpSynchronizeDirectoriesAsyncResult.cs index 0d2644de5..35aacd200 100644 --- a/src/Renci.SshNet/Sftp/SftpSynchronizeDirectoriesAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpSynchronizeDirectoriesAsyncResult.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; -using Renci.SshNet.Common; using System.IO; +using Renci.SshNet.Common; + namespace Renci.SshNet.Sftp { /// @@ -16,11 +17,11 @@ public class SftpSynchronizeDirectoriesAsyncResult : AsyncResult - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The async callback. /// The state. - public SftpSynchronizeDirectoriesAsyncResult(AsyncCallback asyncCallback, Object state) + public SftpSynchronizeDirectoriesAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) { } diff --git a/src/Renci.SshNet/Sftp/SftpUploadAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpUploadAsyncResult.cs index 5f586daf5..10069b259 100644 --- a/src/Renci.SshNet/Sftp/SftpUploadAsyncResult.cs +++ b/src/Renci.SshNet/Sftp/SftpUploadAsyncResult.cs @@ -1,4 +1,5 @@ using System; + using Renci.SshNet.Common; namespace Renci.SshNet.Sftp @@ -9,7 +10,7 @@ namespace Renci.SshNet.Sftp public class SftpUploadAsyncResult : AsyncResult { /// - /// Gets or sets a value indicating whether to cancel asynchronous upload operation + /// Gets or sets a value indicating whether to cancel asynchronous upload operation. /// /// /// true if upload operation to be canceled; otherwise, false. @@ -29,7 +30,7 @@ public class SftpUploadAsyncResult : AsyncResult /// /// The async callback. /// The state. - public SftpUploadAsyncResult(AsyncCallback asyncCallback, Object state) + public SftpUploadAsyncResult(AsyncCallback asyncCallback, object state) : base(asyncCallback, state) { } diff --git a/src/Renci.SshNet/Shell.cs b/src/Renci.SshNet/Shell.cs index 3e68e6b12..63ebcf7e7 100644 --- a/src/Renci.SshNet/Shell.cs +++ b/src/Renci.SshNet/Shell.cs @@ -1,32 +1,33 @@ using System; +using System.Collections.Generic; using System.IO; using System.Threading; + +using Renci.SshNet.Abstractions; using Renci.SshNet.Channels; using Renci.SshNet.Common; -using System.Collections.Generic; -using Renci.SshNet.Abstractions; namespace Renci.SshNet { /// - /// Represents instance of the SSH shell object + /// Represents instance of the SSH shell object. /// public class Shell : IDisposable { private readonly ISession _session; - private IChannelSession _channel; - private EventWaitHandle _channelClosedWaitHandle; - private Stream _input; private readonly string _terminalName; private readonly uint _columns; private readonly uint _rows; private readonly uint _width; private readonly uint _height; private readonly IDictionary _terminalModes; - private EventWaitHandle _dataReaderTaskCompleted; private readonly Stream _outputStream; private readonly Stream _extendedOutputStream; private readonly int _bufferSize; + private EventWaitHandle _dataReaderTaskCompleted; + private IChannelSession _channel; + private EventWaitHandle _channelClosedWaitHandle; + private Stream _input; /// /// Gets a value indicating whether this shell is started. @@ -101,10 +102,7 @@ public void Start() throw new SshException("Shell is started."); } - if (Starting != null) - { - Starting(this, new EventArgs()); - } + Starting?.Invoke(this, new EventArgs()); _channel = _session.CreateChannelSession(); _channel.DataReceived += Channel_DataReceived; @@ -114,13 +112,13 @@ public void Start() _session.ErrorOccured += Session_ErrorOccured; _channel.Open(); - _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes); - _channel.SendShellRequest(); + _ = _channel.SendPseudoTerminalRequest(_terminalName, _columns, _rows, _width, _height, _terminalModes); + _ = _channel.SendShellRequest(); - _channelClosedWaitHandle = new AutoResetEvent(false); + _channelClosedWaitHandle = new AutoResetEvent(initialState: false); - // Start input stream listener - _dataReaderTaskCompleted = new ManualResetEvent(false); + // Start input stream listener + _dataReaderTaskCompleted = new ManualResetEvent(initialState: false); ThreadAbstraction.ExecuteThread(() => { try @@ -148,16 +146,13 @@ public void Start() } finally { - _dataReaderTaskCompleted.Set(); + _ = _dataReaderTaskCompleted.Set(); } }); IsStarted = true; - if (Started != null) - { - Started(this, new EventArgs()); - } + Started?.Invoke(this, EventArgs.Empty); } /// @@ -171,10 +166,7 @@ public void Stop() throw new SshException("Shell is not started."); } - if (_channel != null) - { - _channel.Dispose(); - } + _channel?.Dispose(); } private void Session_ErrorOccured(object sender, ExceptionEventArgs e) @@ -184,11 +176,7 @@ private void Session_ErrorOccured(object sender, ExceptionEventArgs e) private void RaiseError(ExceptionEventArgs e) { - var handler = ErrorOccurred; - if (handler != null) - { - handler(this, e); - } + ErrorOccurred?.Invoke(this, e); } private void Session_Disconnected(object sender, EventArgs e) @@ -198,35 +186,29 @@ private void Session_Disconnected(object sender, EventArgs e) private void Channel_ExtendedDataReceived(object sender, ChannelExtendedDataEventArgs e) { - if (_extendedOutputStream != null) - { - _extendedOutputStream.Write(e.Data, 0, e.Data.Length); - } + _extendedOutputStream?.Write(e.Data, 0, e.Data.Length); } private void Channel_DataReceived(object sender, ChannelDataEventArgs e) { - if (_outputStream != null) - { - _outputStream.Write(e.Data, 0, e.Data.Length); - } + _outputStream?.Write(e.Data, 0, e.Data.Length); } private void Channel_Closed(object sender, ChannelEventArgs e) { if (Stopping != null) { - // Handle event on different thread - ThreadAbstraction.ExecuteThread(() => Stopping(this, new EventArgs())); + // Handle event on different thread + ThreadAbstraction.ExecuteThread(() => Stopping(this, EventArgs.Empty)); } _channel.Dispose(); - _channelClosedWaitHandle.Set(); + _ = _channelClosedWaitHandle.Set(); _input.Dispose(); _input = null; - _dataReaderTaskCompleted.WaitOne(_session.ConnectionInfo.Timeout); + _ = _dataReaderTaskCompleted.WaitOne(_session.ConnectionInfo.Timeout); _dataReaderTaskCompleted.Dispose(); _dataReaderTaskCompleted = null; @@ -238,8 +220,8 @@ private void Channel_Closed(object sender, ChannelEventArgs e) if (Stopped != null) { - // Handle event on different thread - ThreadAbstraction.ExecuteThread(() => Stopped(this, new EventArgs())); + // Handle event on different thread + ThreadAbstraction.ExecuteThread(() => Stopped(this, EventArgs.Empty)); } _channel = null; @@ -255,14 +237,14 @@ private void Channel_Closed(object sender, ChannelEventArgs e) private void UnsubscribeFromSessionEvents(ISession session) { if (session == null) + { return; + } session.Disconnected -= Session_Disconnected; session.ErrorOccured -= Session_ErrorOccured; } - #region IDisposable Members - private bool _disposed; /// @@ -270,18 +252,20 @@ private void UnsubscribeFromSessionEvents(ISession session) /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_disposed) + { return; + } if (disposing) { @@ -313,15 +297,11 @@ protected virtual void Dispose(bool disposing) } /// - /// Releases unmanaged resources and performs other cleanup operations before the - /// is reclaimed by garbage collection. + /// Finalizes an instance of the class. /// ~Shell() { - Dispose(false); + Dispose(disposing: false); } - - #endregion - } } diff --git a/src/Renci.SshNet/ShellStream.cs b/src/Renci.SshNet/ShellStream.cs index 3274fe19c..004b962a3 100644 --- a/src/Renci.SshNet/ShellStream.cs +++ b/src/Renci.SshNet/ShellStream.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; -using System.Text; using System.IO; -using Renci.SshNet.Channels; -using Renci.SshNet.Common; -using System.Threading; +using System.Text; using System.Text.RegularExpressions; +using System.Threading; + using Renci.SshNet.Abstractions; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; namespace Renci.SshNet { @@ -23,7 +24,7 @@ public class ShellStream : Stream private readonly Queue _incoming; private readonly Queue _outgoing; private IChannelSession _channel; - private AutoResetEvent _dataReceived = new AutoResetEvent(false); + private AutoResetEvent _dataReceived = new AutoResetEvent(initialState: false); private bool _isDisposed; /// @@ -37,7 +38,7 @@ public class ShellStream : Stream public event EventHandler ErrorOccurred; /// - /// Gets a value that indicates whether data is available on the to be read. + /// Gets a value indicating whether data is available on the to be read. /// /// /// true if data is available to be read; otherwise, false. @@ -65,13 +66,13 @@ internal int BufferSize } /// - /// Initializes a new instance. + /// Initializes a new instance of the class. /// /// The SSH session. /// The TERM environment variable. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. /// The terminal mode values. /// The size of the buffer. @@ -95,10 +96,12 @@ internal ShellStream(ISession session, string terminalName, uint columns, uint r try { _channel.Open(); + if (!_channel.SendPseudoTerminalRequest(terminalName, columns, rows, width, height, terminalModeValues)) { throw new SshException("The pseudo-terminal request was not accepted by the server. Consult the server log for more information."); } + if (!_channel.SendShellRequest()) { throw new SshException("The request to start a shell was not accepted by the server. Consult the server log for more information."); @@ -112,8 +115,6 @@ internal ShellStream(ISession session, string terminalName, uint columns, uint r } } - #region Stream overide methods - /// /// Gets a value indicating whether the current stream supports reading. /// @@ -150,7 +151,7 @@ public override bool CanWrite /// /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device. /// - /// An I/O error occurs. + /// An I/O error occurs. /// Methods were called after the stream was closed. public override void Flush() { @@ -189,9 +190,9 @@ public override long Length /// /// The current position within the stream. /// - /// An I/O error occurs. - /// The stream does not support seeking. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support seeking. + /// Methods were called after the stream was closed. public override long Position { get { return 0; } @@ -207,12 +208,12 @@ public override long Position /// /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached. /// - /// The sum of and is larger than the buffer length. - /// is null. - /// or is negative. - /// An I/O error occurs. - /// The stream does not support reading. - /// Methods were called after the stream was closed. + /// The sum of and is larger than the buffer length. + /// is null. + /// or is negative. + /// An I/O error occurs. + /// The stream does not support reading. + /// Methods were called after the stream was closed. public override int Read(byte[] buffer, int offset, int count) { var i = 0; @@ -232,13 +233,13 @@ public override int Read(byte[] buffer, int offset, int count) /// This method is not supported. /// /// A byte offset relative to the parameter. - /// A value of type indicating the reference point used to obtain the new position. + /// A value of type indicating the reference point used to obtain the new position. /// /// The new position within the current stream. /// - /// An I/O error occurs. - /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); @@ -248,9 +249,9 @@ public override long Seek(long offset, SeekOrigin origin) /// This method is not supported. /// /// The desired length of the current stream in bytes. - /// An I/O error occurs. - /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. - /// Methods were called after the stream was closed. + /// An I/O error occurs. + /// The stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. + /// Methods were called after the stream was closed. public override void SetLength(long value) { throw new NotSupportedException(); @@ -262,12 +263,12 @@ public override void SetLength(long value) /// An array of bytes. This method copies bytes from to the current stream. /// The zero-based byte offset in at which to begin copying bytes to the current stream. /// The number of bytes to be written to the current stream. - /// The sum of and is greater than the buffer length. - /// is null. - /// or is negative. - /// An I/O error occurs. - /// The stream does not support writing. - /// Methods were called after the stream was closed. + /// The sum of and is greater than the buffer length. + /// is null. + /// or is negative. + /// An I/O error occurs. + /// The stream does not support writing. + /// Methods were called after the stream was closed. public override void Write(byte[] buffer, int offset, int count) { foreach (var b in buffer.Take(offset, count)) @@ -281,8 +282,6 @@ public override void Write(byte[] buffer, int offset, int count) } } - #endregion - /// /// Expects the specified expression and performs action when one is found. /// @@ -323,8 +322,8 @@ public void Expect(TimeSpan timeout, params ExpectAction[] expectActions) for (var i = 0; i < match.Index + match.Length && _incoming.Count > 0; i++) { - // Remove processed items from the queue - _incoming.Dequeue(); + // Remove processed items from the queue + _ = _incoming.Dequeue(); } expectAction.Action(result); @@ -345,7 +344,7 @@ public void Expect(TimeSpan timeout, params ExpectAction[] expectActions) } else { - _dataReceived.WaitOne(); + _ = _dataReceived.WaitOne(); } } } @@ -361,7 +360,7 @@ public void Expect(TimeSpan timeout, params ExpectAction[] expectActions) /// public IAsyncResult BeginExpect(params ExpectAction[] expectActions) { - return BeginExpect(TimeSpan.Zero, null, null, expectActions); + return BeginExpect(TimeSpan.Zero, callback: null, state: null, expectActions); } /// @@ -374,7 +373,7 @@ public IAsyncResult BeginExpect(params ExpectAction[] expectActions) /// public IAsyncResult BeginExpect(AsyncCallback callback, params ExpectAction[] expectActions) { - return BeginExpect(TimeSpan.Zero, callback, null, expectActions); + return BeginExpect(TimeSpan.Zero, callback, state: null, expectActions); } /// @@ -405,21 +404,19 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object { var text = string.Empty; - // Create new AsyncResult object + // Create new AsyncResult object var asyncResult = new ExpectAsyncResult(callback, state); - // Execute callback on different thread + // Execute callback on different thread ThreadAbstraction.ExecuteThread(() => { string expectActionResult = null; try { - do { lock (_incoming) { - if (_incoming.Count > 0) { text = _encoding.GetString(_incoming.ToArray(), 0, _incoming.Count); @@ -437,16 +434,12 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object for (var i = 0; i < match.Index + match.Length && _incoming.Count > 0; i++) { - // Remove processed items from the queue - _incoming.Dequeue(); + // Remove processed items from the queue + _ = _incoming.Dequeue(); } expectAction.Action(result); - - if (callback != null) - { - callback(asyncResult); - } + callback?.Invoke(asyncResult); expectActionResult = result; } } @@ -454,30 +447,30 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object } if (expectActionResult != null) + { break; + } if (timeout.Ticks > 0) { if (!_dataReceived.WaitOne(timeout)) { - if (callback != null) - { - callback(asyncResult); - } + callback?.Invoke(asyncResult); break; } } else { - _dataReceived.WaitOne(); + _ = _dataReceived.WaitOne(); } - } while (true); + } + while (true); - asyncResult.SetAsCompleted(expectActionResult, true); + asyncResult.SetAsCompleted(expectActionResult, completedSynchronously: true); } catch (Exception exp) { - asyncResult.SetAsCompleted(exp, true); + asyncResult.SetAsCompleted(exp, completedSynchronously: true); } }); @@ -491,10 +484,10 @@ public IAsyncResult BeginExpect(TimeSpan timeout, AsyncCallback callback, object /// Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult. public string EndExpect(IAsyncResult asyncResult) { - var ar = asyncResult as ExpectAsyncResult; - - if (ar == null || ar.EndInvokeCalled) + if (asyncResult is not ExpectAsyncResult ar || ar.EndInvokeCalled) + { throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); + } // Wait for operation to complete, then return result or throw exception return ar.EndInvoke(); @@ -563,11 +556,12 @@ public string Expect(Regex regex, TimeSpan timeout) if (match.Success) { - // Remove processed items from the queue + // Remove processed items from the queue for (var i = 0; i < match.Index + match.Length && _incoming.Count > 0; i++) { - _incoming.Dequeue(); + _ = _incoming.Dequeue(); } + break; } } @@ -581,9 +575,8 @@ public string Expect(Regex regex, TimeSpan timeout) } else { - _dataReceived.WaitOne(); + _ = _dataReceived.WaitOne(); } - } return text; @@ -631,7 +624,9 @@ public string ReadLine(TimeSpan timeout) // remove processed bytes from the queue for (var i = 0; i < bytesProcessed; i++) - _incoming.Dequeue(); + { + _ = _incoming.Dequeue(); + } break; } @@ -646,9 +641,8 @@ public string ReadLine(TimeSpan timeout) } else { - _dataReceived.WaitOne(); + _ = _dataReceived.WaitOne(); } - } return text; @@ -683,7 +677,9 @@ public string Read() public void Write(string text) { if (text == null) + { return; + } if (_channel == null) { @@ -715,7 +711,9 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); if (_isDisposed) + { return; + } if (disposing) { @@ -753,7 +751,9 @@ protected override void Dispose(bool disposing) private void UnsubscribeFromSessionEvents(ISession session) { if (session == null) + { return; + } session.Disconnected -= Session_Disconnected; session.ErrorOccured -= Session_ErrorOccured; @@ -767,12 +767,14 @@ private void Session_ErrorOccured(object sender, ExceptionEventArgs e) private void Session_Disconnected(object sender, EventArgs e) { if (_channel != null) + { _channel.Dispose(); + } } private void Channel_Closed(object sender, ChannelEventArgs e) { - // TODO: Do we need to call dispose here ?? + // TODO: Do we need to call dispose here ?? Dispose(); } @@ -781,31 +783,27 @@ private void Channel_DataReceived(object sender, ChannelDataEventArgs e) lock (_incoming) { foreach (var b in e.Data) + { _incoming.Enqueue(b); + } } if (_dataReceived != null) - _dataReceived.Set(); + { + _ = _dataReceived.Set(); + } OnDataReceived(e.Data); } private void OnRaiseError(ExceptionEventArgs e) { - var handler = ErrorOccurred; - if (handler != null) - { - handler(this, e); - } + ErrorOccurred?.Invoke(this, e); } private void OnDataReceived(byte[] data) { - var handler = DataReceived; - if (handler != null) - { - handler(this, new ShellDataEventArgs(data)); - } + DataReceived?.Invoke(this, new ShellDataEventArgs(data)); } } } diff --git a/src/Renci.SshNet/SshClient.cs b/src/Renci.SshNet/SshClient.cs index 881a173d4..26a3cb1b4 100644 --- a/src/Renci.SshNet/SshClient.cs +++ b/src/Renci.SshNet/SshClient.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Text; using System.Diagnostics.CodeAnalysis; +using System.IO; using System.Net; +using System.Text; + using Renci.SshNet.Common; namespace Renci.SshNet @@ -14,7 +15,7 @@ namespace Renci.SshNet public class SshClient : BaseClient { /// - /// Holds the list of forwarded ports + /// Holds the list of forwarded ports. /// private readonly List _forwardedPorts; @@ -39,8 +40,6 @@ public IEnumerable ForwardedPorts } } - #region Constructors - /// /// Initializes a new instance of the class. /// @@ -53,7 +52,7 @@ public IEnumerable ForwardedPorts /// /// is null. public SshClient(ConnectionInfo connectionInfo) - : this(connectionInfo, false) + : this(connectionInfo, ownsConnectionInfo: false) { } @@ -69,7 +68,7 @@ public SshClient(ConnectionInfo connectionInfo) /// is not within and . [SuppressMessage("Microsoft.Reliability", "C2A000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public SshClient(string host, int port, string username, string password) - : this(new PasswordConnectionInfo(host, port, username, password), true) + : this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true) { } @@ -105,7 +104,7 @@ public SshClient(string host, string username, string password) /// is not within and . [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")] public SshClient(string host, int port, string username, params IPrivateKeySource[] keyFiles) - : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) + : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true) { } @@ -159,8 +158,6 @@ internal SshClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServ _forwardedPorts = new List(); } - #endregion - /// /// Called when client is disconnecting from the server. /// @@ -188,7 +185,10 @@ protected override void OnDisconnecting() public void AddForwardedPort(ForwardedPort port) { if (port == null) - throw new ArgumentNullException("port"); + { + throw new ArgumentNullException(nameof(port)); + } + EnsureSessionIsOpen(); AttachForwardedPort(port); @@ -203,19 +203,23 @@ public void AddForwardedPort(ForwardedPort port) public void RemoveForwardedPort(ForwardedPort port) { if (port == null) - throw new ArgumentNullException("port"); + { + throw new ArgumentNullException(nameof(port)); + } - // Stop port forwarding before removing it + // Stop port forwarding before removing it port.Stop(); DetachForwardedPort(port); - _forwardedPorts.Remove(port); + _ = _forwardedPorts.Remove(port); } private void AttachForwardedPort(ForwardedPort port) { if (port.Session != null && port.Session != Session) + { throw new InvalidOperationException("Forwarded port is already added to a different client."); + } port.Session = Session; } @@ -264,14 +268,14 @@ public SshCommand CreateCommand(string commandText, Encoding encoding) /// /// /// CommandText property is empty. - /// Invalid Operation - An existing channel was used to execute this command. + /// Invalid Operation - An existing channel was used to execute this command. /// Asynchronous operation is already in progress. /// Client is not connected. /// is null. public SshCommand RunCommand(string commandText) { var cmd = CreateCommand(commandText); - cmd.Execute(); + _ = cmd.Execute(); return cmd; } @@ -361,7 +365,7 @@ public Shell CreateShell(Encoding encoding, string input, Stream output, Stream var writer = new StreamWriter(_inputStream, encoding); writer.Write(input); writer.Flush(); - _inputStream.Seek(0, SeekOrigin.Begin); + _ = _inputStream.Seek(0, SeekOrigin.Begin); return CreateShell(_inputStream, output, extendedOutput, terminalName, columns, rows, width, height, terminalModes, bufferSize); } @@ -410,7 +414,7 @@ public Shell CreateShell(Encoding encoding, string input, Stream output, Stream /// The TERM environment variable. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. /// The size of the buffer. /// @@ -438,7 +442,7 @@ public ShellStream CreateShellStream(string terminalName, uint columns, uint row /// The TERM environment variable. /// The terminal width in columns. /// The terminal width in rows. - /// The terminal height in pixels. + /// The terminal width in pixels. /// The terminal height in pixels. /// The size of the buffer. /// The terminal mode values. @@ -479,7 +483,7 @@ protected override void OnDisconnected() } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) @@ -487,7 +491,9 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); if (_isDisposed) + { return; + } if (disposing) { @@ -504,7 +510,9 @@ protected override void Dispose(bool disposing) private void EnsureSessionIsOpen() { if (Session == null) + { throw new SshConnectionException("Client not connected."); + } } } -} \ No newline at end of file +} diff --git a/src/Renci.SshNet/SshCommand.cs b/src/Renci.SshNet/SshCommand.cs index 37e91da08..2fa78d4a5 100644 --- a/src/Renci.SshNet/SshCommand.cs +++ b/src/Renci.SshNet/SshCommand.cs @@ -1,13 +1,14 @@ using System; +using System.Globalization; using System.IO; using System.Text; using System.Threading; + +using Renci.SshNet.Abstractions; using Renci.SshNet.Channels; using Renci.SshNet.Common; using Renci.SshNet.Messages.Connection; using Renci.SshNet.Messages.Transport; -using System.Globalization; -using Renci.SshNet.Abstractions; namespace Renci.SshNet { @@ -16,15 +17,19 @@ namespace Renci.SshNet /// public class SshCommand : IDisposable { - private ISession _session; private readonly Encoding _encoding; + private readonly object _endExecuteLock = new object(); + + private ISession _session; private IChannelSession _channel; private CommandAsyncResult _asyncResult; private AsyncCallback _callback; private EventWaitHandle _sessionErrorOccuredWaitHandle; private Exception _exception; + private StringBuilder _result; + private StringBuilder _error; private bool _hasError; - private readonly object _endExecuteLock = new object(); + private bool _isDisposed; /// /// Gets the command text. @@ -66,7 +71,6 @@ public class SshCommand : IDisposable /// public Stream ExtendedOutputStream { get; private set; } - private StringBuilder _result; /// /// Gets the command execution result. /// @@ -77,23 +81,19 @@ public string Result { get { - if (_result == null) - { - _result = new StringBuilder(); - } + _result ??= new StringBuilder(); if (OutputStream != null && OutputStream.Length > 0) { // do not dispose the StreamReader, as it would also dispose the stream var sr = new StreamReader(OutputStream, _encoding); - _result.Append(sr.ReadToEnd()); + _ = _result.Append(sr.ReadToEnd()); } return _result.ToString(); } } - private StringBuilder _error; /// /// Gets the command execution error. /// @@ -106,20 +106,18 @@ public string Error { if (_hasError) { - if (_error == null) - { - _error = new StringBuilder(); - } + _error ??= new StringBuilder(); if (ExtendedOutputStream != null && ExtendedOutputStream.Length > 0) { // do not dispose the StreamReader, as it would also dispose the stream var sr = new StreamReader(ExtendedOutputStream, _encoding); - _error.Append(sr.ReadToEnd()); + _ = _error.Append(sr.ReadToEnd()); } return _error.ToString(); } + return string.Empty; } } @@ -134,11 +132,19 @@ public string Error internal SshCommand(ISession session, string commandText, Encoding encoding) { if (session == null) - throw new ArgumentNullException("session"); + { + throw new ArgumentNullException(nameof(session)); + } + if (commandText == null) - throw new ArgumentNullException("commandText"); + { + throw new ArgumentNullException(nameof(commandText)); + } + if (encoding == null) - throw new ArgumentNullException("encoding"); + { + throw new ArgumentNullException(nameof(encoding)); + } _session = session; CommandText = commandText; @@ -154,7 +160,7 @@ internal SshCommand(ISession session, string commandText, Encoding encoding) /// Begins an asynchronous command execution. /// /// - /// An that represents the asynchronous command execution, which could still be pending. + /// An that represents the asynchronous command execution, which could still be pending. /// /// /// @@ -164,8 +170,6 @@ internal SshCommand(ISession session, string commandText, Encoding encoding) /// CommandText property is empty. /// Client is not connected. /// Operation has timed out. - /// Asynchronous operation is already in progress. - /// CommandText property is empty. public IAsyncResult BeginExecute() { return BeginExecute(null, null); @@ -176,15 +180,13 @@ public IAsyncResult BeginExecute() /// /// An optional asynchronous callback, to be called when the command execution is complete. /// - /// An that represents the asynchronous command execution, which could still be pending. + /// An that represents the asynchronous command execution, which could still be pending. /// /// Asynchronous operation is already in progress. /// Invalid operation. /// CommandText property is empty. /// Client is not connected. /// Operation has timed out. - /// Asynchronous operation is already in progress. - /// CommandText property is empty. public IAsyncResult BeginExecute(AsyncCallback callback) { return BeginExecute(callback, null); @@ -203,17 +205,15 @@ public IAsyncResult BeginExecute(AsyncCallback callback) /// CommandText property is empty. /// Client is not connected. /// Operation has timed out. - /// Asynchronous operation is already in progress. - /// CommandText property is empty. public IAsyncResult BeginExecute(AsyncCallback callback, object state) { - // Prevent from executing BeginExecute before calling EndExecute + // Prevent from executing BeginExecute before calling EndExecute if (_asyncResult != null && !_asyncResult.EndCalled) { throw new InvalidOperationException("Asynchronous operation is already in progress."); } - // Create new AsyncResult object + // Create new AsyncResult object _asyncResult = new CommandAsyncResult { AsyncWaitHandle = new ManualResetEvent(false), @@ -221,14 +221,16 @@ public IAsyncResult BeginExecute(AsyncCallback callback, object state) AsyncState = state, }; - // When command re-executed again, create a new channel + // When command re-executed again, create a new channel if (_channel != null) { throw new SshException("Invalid operation."); } if (string.IsNullOrEmpty(CommandText)) + { throw new ArgumentException("CommandText property is empty."); + } var outputStream = OutputStream; if (outputStream != null) @@ -244,7 +246,7 @@ public IAsyncResult BeginExecute(AsyncCallback callback, object state) ExtendedOutputStream = null; } - // Initialize output streams + // Initialize output streams OutputStream = new PipeStream(); ExtendedOutputStream = new PipeStream(); @@ -254,7 +256,7 @@ public IAsyncResult BeginExecute(AsyncCallback callback, object state) _channel = CreateChannel(); _channel.Open(); - _channel.SendExecRequest(CommandText); + _ = _channel.SendExecRequest(CommandText); return _asyncResult; } @@ -266,10 +268,10 @@ public IAsyncResult BeginExecute(AsyncCallback callback, object state) /// An optional asynchronous callback, to be called when the command execution is complete. /// A user-provided object that distinguishes this particular asynchronous read request from other requests. /// - /// An that represents the asynchronous command execution, which could still be pending. + /// An that represents the asynchronous command execution, which could still be pending. /// - /// Client is not connected. - /// Operation has timed out. + /// Client is not connected. + /// Operation has timed out. public IAsyncResult BeginExecute(string commandText, AsyncCallback callback, object state) { CommandText = commandText; @@ -291,13 +293,12 @@ public string EndExecute(IAsyncResult asyncResult) { if (asyncResult == null) { - throw new ArgumentNullException("asyncResult"); + throw new ArgumentNullException(nameof(asyncResult)); } - var commandAsyncResult = asyncResult as CommandAsyncResult; - if (commandAsyncResult == null || _asyncResult != commandAsyncResult) + if (asyncResult is not CommandAsyncResult commandAsyncResult || _asyncResult != commandAsyncResult) { - throw new ArgumentException(string.Format("The {0} object was not returned from the corresponding asynchronous method on this class.", typeof(IAsyncResult).Name)); + throw new ArgumentException(string.Format("The {0} object was not returned from the corresponding asynchronous method on this class.", nameof(IAsyncResult))); } lock (_endExecuteLock) @@ -307,7 +308,7 @@ public string EndExecute(IAsyncResult asyncResult) throw new ArgumentException("EndExecute can only be called once for each asynchronous operation."); } - // wait for operation to complete (or time out) + // wait for operation to complete (or time out) WaitOnHandle(_asyncResult.AsyncWaitHandle); UnsubscribeFromEventsAndDisposeChannel(_channel); @@ -328,15 +329,15 @@ public string EndExecute(IAsyncResult asyncResult) /// /// /// - /// Client is not connected. - /// Operation has timed out. + /// Client is not connected. + /// Operation has timed out. public string Execute() { return EndExecute(BeginExecute(null, null)); } /// - /// Cancels command execution in asynchronous scenarios. + /// Cancels command execution in asynchronous scenarios. /// public void CancelAsync() { @@ -351,9 +352,11 @@ public void CancelAsync() /// Executes the specified command text. /// /// The command text. - /// Command execution result - /// Client is not connected. - /// Operation has timed out. + /// + /// The result of the command execution. + /// + /// Client is not connected. + /// Operation has timed out. public string Execute(string commandText) { CommandText = commandText; @@ -373,54 +376,49 @@ private IChannelSession CreateChannel() private void Session_Disconnected(object sender, EventArgs e) { - // If objected is disposed or being disposed don't handle this event + // If objected is disposed or being disposed don't handle this event if (_isDisposed) + { return; + } _exception = new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost); - _sessionErrorOccuredWaitHandle.Set(); + _ = _sessionErrorOccuredWaitHandle.Set(); } private void Session_ErrorOccured(object sender, ExceptionEventArgs e) { - // If objected is disposed or being disposed don't handle this event + // If objected is disposed or being disposed don't handle this event if (_isDisposed) + { return; + } _exception = e.Exception; - _sessionErrorOccuredWaitHandle.Set(); + _ = _sessionErrorOccuredWaitHandle.Set(); } private void Channel_Closed(object sender, ChannelEventArgs e) { - var outputStream = OutputStream; - if (outputStream != null) - { - outputStream.Flush(); - } - - var extendedOutputStream = ExtendedOutputStream; - if (extendedOutputStream != null) - { - extendedOutputStream.Flush(); - } + OutputStream?.Flush(); + ExtendedOutputStream?.Flush(); _asyncResult.IsCompleted = true; if (_callback != null) { - // Execute callback on different thread + // Execute callback on different thread ThreadAbstraction.ExecuteThread(() => _callback(_asyncResult)); } - ((EventWaitHandle) _asyncResult.AsyncWaitHandle).Set(); + + _ = ((EventWaitHandle) _asyncResult.AsyncWaitHandle).Set(); } private void Channel_RequestReceived(object sender, ChannelRequestEventArgs e) { - var exitStatusInfo = e.Info as ExitStatusRequestInfo; - if (exitStatusInfo != null) + if (e.Info is ExitStatusRequestInfo exitStatusInfo) { ExitStatus = (int) exitStatusInfo.ExitStatus; @@ -501,7 +499,9 @@ private void WaitOnHandle(WaitHandle waitHandle) private void UnsubscribeFromEventsAndDisposeChannel(IChannel channel) { if (channel == null) + { return; + } // unsubscribe from events as we do not want to be signaled should these get fired // during the dispose of the channel @@ -514,27 +514,25 @@ private void UnsubscribeFromEventsAndDisposeChannel(IChannel channel) channel.Dispose(); } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -583,14 +581,13 @@ protected virtual void Dispose(bool disposing) } /// + /// Finalizes an instance of the class. /// Releases unmanaged resources and performs other cleanup operations before the /// is reclaimed by garbage collection. /// ~SshCommand() { - Dispose(false); + Dispose(disposing: false); } - - #endregion } } diff --git a/src/Renci.SshNet/SshMessageFactory.cs b/src/Renci.SshNet/SshMessageFactory.cs index 153024dbf..61952f4b5 100644 --- a/src/Renci.SshNet/SshMessageFactory.cs +++ b/src/Renci.SshNet/SshMessageFactory.cs @@ -9,13 +9,13 @@ namespace Renci.SshNet { - internal class SshMessageFactory + internal sealed class SshMessageFactory { private readonly MessageMetadata[] _enabledMessagesByNumber; private readonly bool[] _activatedMessagesById; internal static readonly MessageMetadata[] AllMessages; - private static readonly IDictionary MessagesByName; + private static readonly Dictionary MessagesByName; /// /// Defines the highest message number that is currently supported. @@ -30,40 +30,40 @@ internal class SshMessageFactory static SshMessageFactory() { AllMessages = new MessageMetadata[] - { - new MessageMetadata(0, "SSH_MSG_KEXINIT", 20), - new MessageMetadata (1, "SSH_MSG_NEWKEYS", 21), - new MessageMetadata (2, "SSH_MSG_REQUEST_FAILURE", 82), - new MessageMetadata (3, "SSH_MSG_CHANNEL_OPEN_FAILURE", 92), - new MessageMetadata (4, "SSH_MSG_CHANNEL_FAILURE", 100), - new MessageMetadata (5, "SSH_MSG_CHANNEL_EXTENDED_DATA", 95), - new MessageMetadata (6, "SSH_MSG_CHANNEL_DATA", 94), - new MessageMetadata (7, "SSH_MSG_CHANNEL_REQUEST", 98), - new MessageMetadata (8, "SSH_MSG_USERAUTH_BANNER", 53), - new MessageMetadata (9, "SSH_MSG_USERAUTH_INFO_RESPONSE", 61), - new MessageMetadata (10, "SSH_MSG_USERAUTH_FAILURE", 51), - new MessageMetadata (11, "SSH_MSG_DEBUG", 4), - new MessageMetadata (12, "SSH_MSG_GLOBAL_REQUEST", 80), - new MessageMetadata (13, "SSH_MSG_CHANNEL_OPEN", 90), - new MessageMetadata (14, "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", 91), - new MessageMetadata (15, "SSH_MSG_USERAUTH_INFO_REQUEST", 60), - new MessageMetadata (16, "SSH_MSG_UNIMPLEMENTED", 3), - new MessageMetadata (17, "SSH_MSG_REQUEST_SUCCESS", 81), - new MessageMetadata (18, "SSH_MSG_CHANNEL_SUCCESS", 99), - new MessageMetadata (19, "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", 60), - new MessageMetadata (20, "SSH_MSG_DISCONNECT", 1), - new MessageMetadata (21, "SSH_MSG_USERAUTH_SUCCESS", 52), - new MessageMetadata (22, "SSH_MSG_USERAUTH_PK_OK", 60), - new MessageMetadata (23, "SSH_MSG_IGNORE", 2), - new MessageMetadata (24, "SSH_MSG_CHANNEL_WINDOW_ADJUST", 93), - new MessageMetadata (25, "SSH_MSG_CHANNEL_EOF", 96), - new MessageMetadata (26, "SSH_MSG_CHANNEL_CLOSE", 97), - new MessageMetadata (27, "SSH_MSG_SERVICE_ACCEPT", 6), - new MessageMetadata (28, "SSH_MSG_KEX_DH_GEX_GROUP", 31), - new MessageMetadata (29, "SSH_MSG_KEXDH_REPLY", 31), - new MessageMetadata (30, "SSH_MSG_KEX_DH_GEX_REPLY", 33), - new MessageMetadata (31, "SSH_MSG_KEX_ECDH_REPLY", 31) - }; + { + new MessageMetadata(0, "SSH_MSG_KEXINIT", 20), + new MessageMetadata(1, "SSH_MSG_NEWKEYS", 21), + new MessageMetadata(2, "SSH_MSG_REQUEST_FAILURE", 82), + new MessageMetadata(3, "SSH_MSG_CHANNEL_OPEN_FAILURE", 92), + new MessageMetadata(4, "SSH_MSG_CHANNEL_FAILURE", 100), + new MessageMetadata(5, "SSH_MSG_CHANNEL_EXTENDED_DATA", 95), + new MessageMetadata(6, "SSH_MSG_CHANNEL_DATA", 94), + new MessageMetadata(7, "SSH_MSG_CHANNEL_REQUEST", 98), + new MessageMetadata(8, "SSH_MSG_USERAUTH_BANNER", 53), + new MessageMetadata(9, "SSH_MSG_USERAUTH_INFO_RESPONSE", 61), + new MessageMetadata(10, "SSH_MSG_USERAUTH_FAILURE", 51), + new MessageMetadata(11, "SSH_MSG_DEBUG", 4), + new MessageMetadata(12, "SSH_MSG_GLOBAL_REQUEST", 80), + new MessageMetadata(13, "SSH_MSG_CHANNEL_OPEN", 90), + new MessageMetadata(14, "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", 91), + new MessageMetadata(15, "SSH_MSG_USERAUTH_INFO_REQUEST", 60), + new MessageMetadata(16, "SSH_MSG_UNIMPLEMENTED", 3), + new MessageMetadata(17, "SSH_MSG_REQUEST_SUCCESS", 81), + new MessageMetadata(18, "SSH_MSG_CHANNEL_SUCCESS", 99), + new MessageMetadata(19, "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", 60), + new MessageMetadata(20, "SSH_MSG_DISCONNECT", 1), + new MessageMetadata(21, "SSH_MSG_USERAUTH_SUCCESS", 52), + new MessageMetadata(22, "SSH_MSG_USERAUTH_PK_OK", 60), + new MessageMetadata(23, "SSH_MSG_IGNORE", 2), + new MessageMetadata(24, "SSH_MSG_CHANNEL_WINDOW_ADJUST", 93), + new MessageMetadata(25, "SSH_MSG_CHANNEL_EOF", 96), + new MessageMetadata(26, "SSH_MSG_CHANNEL_CLOSE", 97), + new MessageMetadata(27, "SSH_MSG_SERVICE_ACCEPT", 6), + new MessageMetadata(28, "SSH_MSG_KEX_DH_GEX_GROUP", 31), + new MessageMetadata(29, "SSH_MSG_KEXDH_REPLY", 31), + new MessageMetadata(30, "SSH_MSG_KEX_DH_GEX_REPLY", 33), + new MessageMetadata(31, "SSH_MSG_KEX_ECDH_REPLY", 31) + }; MessagesByName = new Dictionary(AllMessages.Length); for (var i = 0; i < AllMessages.Length; i++) @@ -73,6 +73,9 @@ static SshMessageFactory() } } + /// + /// Initializes a new instance of the class. + /// public SshMessageFactory() { _activatedMessagesById = new bool[TotalMessageCount]; @@ -129,7 +132,7 @@ public void DisableNonKeyExchangeMessages() var messageMetadata = AllMessages[i]; var messageNumber = messageMetadata.Number; - if ((messageNumber > 2 && messageNumber < 20) || messageNumber > 30) + if (messageNumber is (> 2 and < 20) or > 30) { _enabledMessagesByNumber[messageNumber] = null; } @@ -143,15 +146,18 @@ public void EnableActivatedMessages() var messageMetadata = AllMessages[i]; if (!_activatedMessagesById[messageMetadata.Id]) + { continue; + } var enabledMessageMetadata = _enabledMessagesByNumber[messageMetadata.Number]; if (enabledMessageMetadata != null && enabledMessageMetadata != messageMetadata) { throw CreateMessageTypeAlreadyEnabledForOtherMessageException(messageMetadata.Number, - messageMetadata.Name, - enabledMessageMetadata.Name); + messageMetadata.Name, + enabledMessageMetadata.Name); } + _enabledMessagesByNumber[messageMetadata.Number] = messageMetadata; } } @@ -159,13 +165,13 @@ public void EnableActivatedMessages() public void EnableAndActivateMessage(string messageName) { if (messageName == null) - throw new ArgumentNullException("messageName"); + { + throw new ArgumentNullException(nameof(messageName)); + } lock (this) { - MessageMetadata messageMetadata; - - if (!MessagesByName.TryGetValue(messageName, out messageMetadata)) + if (!MessagesByName.TryGetValue(messageName, out var messageMetadata)) { throw CreateMessageNotSupportedException(messageName); } @@ -186,13 +192,13 @@ public void EnableAndActivateMessage(string messageName) public void DisableAndDeactivateMessage(string messageName) { if (messageName == null) - throw new ArgumentNullException("messageName"); + { + throw new ArgumentNullException(nameof(messageName)); + } lock (this) { - MessageMetadata messageMetadata; - - if (!MessagesByName.TryGetValue(messageName, out messageMetadata)) + if (!MessagesByName.TryGetValue(messageName, out var messageMetadata)) { throw CreateMessageNotSupportedException(messageName); } @@ -201,8 +207,8 @@ public void DisableAndDeactivateMessage(string messageName) if (enabledMessageMetadata != null && enabledMessageMetadata != messageMetadata) { throw CreateMessageTypeAlreadyEnabledForOtherMessageException(messageMetadata.Number, - messageMetadata.Name, - enabledMessageMetadata.Name); + messageMetadata.Name, + enabledMessageMetadata.Name); } _activatedMessagesById[messageMetadata.Id] = false; @@ -245,7 +251,8 @@ protected MessageMetadata(byte id, string name, byte number) public abstract Message Create(); } - internal class MessageMetadata : MessageMetadata where T : Message, new() + internal sealed class MessageMetadata : MessageMetadata + where T : Message, new() { public MessageMetadata(byte id, string name, byte number) : base(id, name, number) diff --git a/src/Renci.SshNet/SubsystemSession.cs b/src/Renci.SshNet/SubsystemSession.cs index 943a2db9e..922312e37 100644 --- a/src/Renci.SshNet/SubsystemSession.cs +++ b/src/Renci.SshNet/SubsystemSession.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Threading; + using Renci.SshNet.Abstractions; using Renci.SshNet.Channels; using Renci.SshNet.Common; @@ -8,7 +9,7 @@ namespace Renci.SshNet { /// - /// Base class for SSH subsystem implementations + /// Base class for SSH subsystem implementations. /// internal abstract class SubsystemSession : ISubsystemSession { @@ -18,13 +19,14 @@ internal abstract class SubsystemSession : ISubsystemSession /// private const int SystemWaitHandleCount = 3; - private ISession _session; private readonly string _subsystemName; + private ISession _session; private IChannelSession _channel; private Exception _exception; private EventWaitHandle _errorOccuredWaitHandle = new ManualResetEvent(false); private EventWaitHandle _sessionDisconnectedWaitHandle = new ManualResetEvent(false); private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(false); + private bool _isDisposed; /// /// Gets or set the number of seconds to wait for an operation to complete. @@ -72,7 +74,7 @@ public bool IsOpen } /// - /// Initializes a new instance of the SubsystemSession class. + /// Initializes a new instance of the class. /// /// The session. /// Name of the subsystem. @@ -81,9 +83,14 @@ public bool IsOpen protected SubsystemSession(ISession session, string subsystemName, int operationTimeout) { if (session == null) - throw new ArgumentNullException("session"); + { + throw new ArgumentNullException(nameof(session)); + } + if (subsystemName == null) - throw new ArgumentNullException("subsystemName"); + { + throw new ArgumentNullException(nameof(subsystemName)); + } _session = session; _subsystemName = subsystemName; @@ -101,13 +108,15 @@ public void Connect() EnsureNotDisposed(); if (IsOpen) + { throw new InvalidOperationException("The session is already connected."); + } // reset waithandles in case we're reconnecting - _errorOccuredWaitHandle.Reset(); - _sessionDisconnectedWaitHandle.Reset(); - _sessionDisconnectedWaitHandle.Reset(); - _channelClosedWaitHandle.Reset(); + _ = _errorOccuredWaitHandle.Reset(); + _ = _sessionDisconnectedWaitHandle.Reset(); + _ = _sessionDisconnectedWaitHandle.Reset(); + _ = _channelClosedWaitHandle.Reset(); _session.ErrorOccured += Session_ErrorOccured; _session.Disconnected += Session_Disconnected; @@ -122,6 +131,7 @@ public void Connect() { // close channel session Disconnect(); + // signal subsystem failure throw new SshException(string.Format(CultureInfo.InvariantCulture, "Subsystem '{0}' could not be executed.", @@ -182,9 +192,7 @@ protected void RaiseError(Exception error) DiagnosticAbstraction.Log("Raised exception: " + error); - var errorOccuredWaitHandle = _errorOccuredWaitHandle; - if (errorOccuredWaitHandle != null) - errorOccuredWaitHandle.Set(); + _ = _errorOccuredWaitHandle?.Set(); SignalErrorOccurred(error); } @@ -208,9 +216,7 @@ private void Channel_Exception(object sender, ExceptionEventArgs e) private void Channel_Closed(object sender, ChannelEventArgs e) { - var channelClosedWaitHandle = _channelClosedWaitHandle; - if (channelClosedWaitHandle != null) - channelClosedWaitHandle.Set(); + _ = _channelClosedWaitHandle?.Set(); } /// @@ -429,9 +435,7 @@ public WaitHandle[] CreateWaitHandleArray(params WaitHandle[] waitHandles) private void Session_Disconnected(object sender, EventArgs e) { - var sessionDisconnectedWaitHandle = _sessionDisconnectedWaitHandle; - if (sessionDisconnectedWaitHandle != null) - sessionDisconnectedWaitHandle.Set(); + _ = _sessionDisconnectedWaitHandle?.Set(); SignalDisconnected(); } @@ -443,26 +447,20 @@ private void Session_ErrorOccured(object sender, ExceptionEventArgs e) private void SignalErrorOccurred(Exception error) { - var errorOccurred = ErrorOccurred; - if (errorOccurred != null) - { - errorOccurred(this, new ExceptionEventArgs(error)); - } + ErrorOccurred?.Invoke(this, new ExceptionEventArgs(error)); } private void SignalDisconnected() { - var disconnected = Disconnected; - if (disconnected != null) - { - disconnected(this, new EventArgs()); - } + Disconnected?.Invoke(this, EventArgs.Empty); } private void EnsureSessionIsOpen() { if (!IsOpen) + { throw new InvalidOperationException("The session is not open."); + } } /// @@ -475,33 +473,33 @@ private void EnsureSessionIsOpen() private void UnsubscribeFromSessionEvents(ISession session) { if (session == null) + { return; + } session.Disconnected -= Session_Disconnected; session.ErrorOccured -= Session_ErrorOccured; } - #region IDisposable Members - - private bool _isDisposed; - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + Dispose(disposing: true); GC.SuppressFinalize(this); } /// - /// Releases unmanaged and - optionally - managed resources + /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (_isDisposed) + { return; + } if (disposing) { @@ -539,15 +537,15 @@ protected virtual void Dispose(bool disposing) /// ~SubsystemSession() { - Dispose(false); + Dispose(disposing: false); } private void EnsureNotDisposed() { if (_isDisposed) + { throw new ObjectDisposedException(GetType().FullName); + } } - - #endregion } } diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 000000000..ff7c9dbfb --- /dev/null +++ b/stylecop.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "xmlHeader": false, + "documentInternalElements": false + }, + "layoutRules": { + "newlineAtEndOfFile": "require" + }, + "indentation": { + "indentationSize": 4, + "tabSize": 4, + "useTabs": false + }, + "namingRules": { + "allowCommonHungarianPrefixes": false + }, + "orderingRules": { + "systemUsingDirectivesFirst": true, + "usingDirectivesPlacement": "outsideNamespace", + "blankLinesBetweenUsingGroups": "require" + } + } +} diff --git a/test/.editorconfig b/test/.editorconfig new file mode 100644 index 000000000..ff0eebcf3 --- /dev/null +++ b/test/.editorconfig @@ -0,0 +1,111 @@ +[*.cs] + +# Sonar rules + +# S1854: Unused assignments should be removed +# https://rules.sonarsource.com/csharp/RSPEC-1854 +# +# We sometimes increment the value of a variable on each use to make the code future-proof. +# +# For example: +# int idSequence = 0; +# var train1 = new Train { Id = ++idSequence }; +# var train2 = new Train { Id = ++idSequence }; +# +# The increment of 'idSequence' in the last line will cause this diagnostic to be reported. We prefer to keep the increment to make +# sure the value of the variable will remain correct when we introduce a 'train3'. +# +# For unit tests, we do not care about this diagnostic. +dotnet_diagnostic.S1854.severity = none + +#### StyleCop rules #### + +# SA1202: Elements must be ordered by access +dotnet_diagnostic.SA1202.severity = none + +# SA1600: Elements must be documented +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1600.severity = none + +# SA1601: Partial elements should be documented +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1601.severity = none + +# SA1602: Enumeration items must be documented +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1602.severity = none + +# SA1604: Element documentation should have summary +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.SA1604.severity = none + +# SA1606: Element documentation should have summary text +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.SA1606.severity = none + +# SA1607: Partial element documentation should have summary text +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1607.severity = none + +# SA1611: Element parameters must be documented +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1611.severity = none + +# SA1614: Element parameter documentation must have text +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.SA1614.severity = none + +# SA1615: Element return value must be documented +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1615.severity = none + +# SA1616: Element return value documentation should have text +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.SA1616.severity = none + +# SA1623: Property summary documentation must match accessors +# +# TODO: Remove this when code has been updated! +dotnet_diagnostic.SA1623.severity = none + +# SA1629: Documentation text must end with a period +# +# For unit test projects, we do not care about documentation. +dotnet_diagnostic.SA1629.severity = none + +#### .NET Compiler Platform analysers rules #### + +# CA1001: Types that own disposable fields should be disposable +# +# We do not care about this for unit tests. +dotnet_diagnostic.CA1001.severity = none + +# CA1707: Identifiers should not contain underscores +# +# We frequently use underscores in test classes and test methods. +dotnet_diagnostic.CA1707.severity = none + +# CA1711: Identifiers should not have incorrect suffix +# +# We frequently define test classes and test method with a suffix that refers to a type. +dotnet_diagnostic.CA1711.severity = none + +# CA1720: Identifiers should not contain type names +# +# We do not care about this for unit tests. +dotnet_diagnostic.CA1720.severity = none + +# CA5394: Do not use insecure randomness +# +# We do not care about this for unit tests. +dotnet_diagnostic.CA5394.severity = none diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 000000000..1e96f3c4d --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,16 @@ + + + + + + $(NoWarn);CS1591 + +