├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── MANIFEST.in ├── Makefile ├── README ├── debian ├── README.Debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── pycompat ├── python-libssh2.examples ├── rules └── watch ├── examples ├── scp_upload.py ├── sftp_listdir.py ├── ssh.py ├── ssh_exec.py ├── ssh_exec2.py ├── ssh_publickey.py └── ssh_x11.py ├── libssh2 ├── __init__.py ├── channel.py ├── session.py ├── sftp.py └── version.py ├── setup.py ├── src ├── channel.c ├── channel.h ├── listener.c ├── listener.h ├── pylibssh2.c ├── pylibssh2.h ├── session.c ├── session.h ├── sftp.c ├── sftp.h ├── sftphandle.c ├── sftphandle.h ├── util.c └── util.h └── tests └── test_session.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | build/ 3 | dist/ 4 | doc/ 5 | pylibssh2.egg-info/ 6 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Initial Authors: 2 | 3 | Vincent Jaulin 4 | Sofian Brabez 5 | 6 | Contributors: 7 | 8 | Christophe Grosjean 9 | Cyril Elkaim 11 | Marcin Szewczyk 12 | Benjamin Kerensa 13 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 2.1, February 1999 4 | 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | [This is the first released version of the Lesser GPL. It also counts 11 | as the successor of the GNU Library Public License, version 2, hence 12 | the version number 2.1.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Lesser General Public License, applies to some 22 | specially designated software packages--typically libraries--of the 23 | Free Software Foundation and other authors who decide to use it. You 24 | can use it too, but we suggest you first think carefully about whether 25 | this license or the ordinary General Public License is the better 26 | strategy to use in any particular case, based on the explanations 27 | below. 28 | 29 | When we speak of free software, we are referring to freedom of use, 30 | not price. Our General Public Licenses are designed to make sure that 31 | you have the freedom to distribute copies of free software (and charge 32 | for this service if you wish); that you receive source code or can get 33 | it if you want it; that you can change the software and use pieces of 34 | it in new free programs; and that you are informed that you can do 35 | these things. 36 | 37 | To protect your rights, we need to make restrictions that forbid 38 | distributors to deny you these rights or to ask you to surrender these 39 | rights. These restrictions translate to certain responsibilities for 40 | you if you distribute copies of the library or if you modify it. 41 | 42 | For example, if you distribute copies of the library, whether gratis 43 | or for a fee, you must give the recipients all the rights that we gave 44 | you. You must make sure that they, too, receive or can get the source 45 | code. If you link other code with the library, you must provide 46 | complete object files to the recipients, so that they can relink them 47 | with the library after making changes to the library and recompiling 48 | it. And you must show them these terms so they know their rights. 49 | 50 | We protect your rights with a two-step method: (1) we copyright the 51 | library, and (2) we offer you this license, which gives you legal 52 | permission to copy, distribute and/or modify the library. 53 | 54 | To protect each distributor, we want to make it very clear that 55 | there is no warranty for the free library. Also, if the library is 56 | modified by someone else and passed on, the recipients should know 57 | that what they have is not the original version, so that the original 58 | author's reputation will not be affected by problems that might be 59 | introduced by others. 60 | ^L 61 | Finally, software patents pose a constant threat to the existence of 62 | any free program. We wish to make sure that a company cannot 63 | effectively restrict the users of a free program by obtaining a 64 | restrictive license from a patent holder. Therefore, we insist that 65 | any patent license obtained for a version of the library must be 66 | consistent with the full freedom of use specified in this license. 67 | 68 | Most GNU software, including some libraries, is covered by the 69 | ordinary GNU General Public License. This license, the GNU Lesser 70 | General Public License, applies to certain designated libraries, and 71 | is quite different from the ordinary General Public License. We use 72 | this license for certain libraries in order to permit linking those 73 | libraries into non-free programs. 74 | 75 | When a program is linked with a library, whether statically or using 76 | a shared library, the combination of the two is legally speaking a 77 | combined work, a derivative of the original library. The ordinary 78 | General Public License therefore permits such linking only if the 79 | entire combination fits its criteria of freedom. The Lesser General 80 | Public License permits more lax criteria for linking other code with 81 | the library. 82 | 83 | We call this license the "Lesser" General Public License because it 84 | does Less to protect the user's freedom than the ordinary General 85 | Public License. It also provides other free software developers Less 86 | of an advantage over competing non-free programs. These disadvantages 87 | are the reason we use the ordinary General Public License for many 88 | libraries. However, the Lesser license provides advantages in certain 89 | special circumstances. 90 | 91 | For example, on rare occasions, there may be a special need to 92 | encourage the widest possible use of a certain library, so that it 93 | becomes 94 | a de-facto standard. To achieve this, non-free programs must be 95 | allowed to use the library. A more frequent case is that a free 96 | library does the same job as widely used non-free libraries. In this 97 | case, there is little to gain by limiting the free library to free 98 | software only, so we use the Lesser General Public License. 99 | 100 | In other cases, permission to use a particular library in non-free 101 | programs enables a greater number of people to use a large body of 102 | free software. For example, permission to use the GNU C Library in 103 | non-free programs enables many more people to use the whole GNU 104 | operating system, as well as its variant, the GNU/Linux operating 105 | system. 106 | 107 | Although the Lesser General Public License is Less protective of the 108 | users' freedom, it does ensure that the user of a program that is 109 | linked with the Library has the freedom and the wherewithal to run 110 | that program using a modified version of the Library. 111 | 112 | The precise terms and conditions for copying, distribution and 113 | modification follow. Pay close attention to the difference between a 114 | "work based on the library" and a "work that uses the library". The 115 | former contains code derived from the library, whereas the latter must 116 | be combined with the library in order to run. 117 | ^L 118 | GNU LESSER GENERAL PUBLIC LICENSE 119 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 120 | 121 | 0. This License Agreement applies to any software library or other 122 | program which contains a notice placed by the copyright holder or 123 | other authorized party saying it may be distributed under the terms of 124 | this Lesser General Public License (also called "this License"). 125 | Each licensee is addressed as "you". 126 | 127 | A "library" means a collection of software functions and/or data 128 | prepared so as to be conveniently linked with application programs 129 | (which use some of those functions and data) to form executables. 130 | 131 | The "Library", below, refers to any such software library or work 132 | which has been distributed under these terms. A "work based on the 133 | Library" means either the Library or any derivative work under 134 | copyright law: that is to say, a work containing the Library or a 135 | portion of it, either verbatim or with modifications and/or translated 136 | straightforwardly into another language. (Hereinafter, translation is 137 | included without limitation in the term "modification".) 138 | 139 | "Source code" for a work means the preferred form of the work for 140 | making modifications to it. For a library, complete source code means 141 | all the source code for all modules it contains, plus any associated 142 | interface definition files, plus the scripts used to control 143 | compilation 144 | and installation of the library. 145 | 146 | Activities other than copying, distribution and modification are not 147 | covered by this License; they are outside its scope. The act of 148 | running a program using the Library is not restricted, and output from 149 | such a program is covered only if its contents constitute a work based 150 | on the Library (independent of the use of the Library in a tool for 151 | writing it). Whether that is true depends on what the Library does 152 | and what the program that uses the Library does. 153 | 154 | 1. You may copy and distribute verbatim copies of the Library's 155 | complete source code as you receive it, in any medium, provided that 156 | you conspicuously and appropriately publish on each copy an 157 | appropriate copyright notice and disclaimer of warranty; keep intact 158 | all the notices that refer to this License and to the absence of any 159 | warranty; and distribute a copy of this License along with the 160 | Library. 161 | 162 | You may charge a fee for the physical act of transferring a copy, 163 | and you may at your option offer warranty protection in exchange for a 164 | fee. 165 | 166 | 2. You may modify your copy or copies of the Library or any portion 167 | of it, thus forming a work based on the Library, and copy and 168 | distribute such modifications or work under the terms of Section 1 169 | above, provided that you also meet all of these conditions: 170 | 171 | a) The modified work must itself be a software library. 172 | 173 | b) You must cause the files modified to carry prominent notices 174 | stating that you changed the files and the date of any change. 175 | 176 | c) You must cause the whole of the work to be licensed at no 177 | charge to all third parties under the terms of this License. 178 | 179 | d) If a facility in the modified Library refers to a function or a 180 | table of data to be supplied by an application program that uses 181 | the facility, other than as an argument passed when the facility 182 | is invoked, then you must make a good faith effort to ensure that, 183 | in the event an application does not supply such function or 184 | table, the facility still operates, and performs whatever part of 185 | its purpose remains meaningful. 186 | 187 | (For example, a function in a library to compute square roots has 188 | a purpose that is entirely well-defined independent of the 189 | application. Therefore, Subsection 2d requires that any 190 | application-supplied function or table used by this function must 191 | be optional: if the application does not supply it, the square 192 | root function must still compute square roots.) 193 | 194 | These requirements apply to the modified work as a whole. If 195 | identifiable sections of that work are not derived from the Library, 196 | and can be reasonably considered independent and separate works in 197 | themselves, then this License, and its terms, do not apply to those 198 | sections when you distribute them as separate works. But when you 199 | distribute the same sections as part of a whole which is a work based 200 | on the Library, the distribution of the whole must be on the terms of 201 | this License, whose permissions for other licensees extend to the 202 | entire whole, and thus to each and every part regardless of who wrote 203 | it. 204 | 205 | Thus, it is not the intent of this section to claim rights or contest 206 | your rights to work written entirely by you; rather, the intent is to 207 | exercise the right to control the distribution of derivative or 208 | collective works based on the Library. 209 | 210 | In addition, mere aggregation of another work not based on the Library 211 | with the Library (or with a work based on the Library) on a volume of 212 | a storage or distribution medium does not bring the other work under 213 | the scope of this License. 214 | 215 | 3. You may opt to apply the terms of the ordinary GNU General Public 216 | License instead of this License to a given copy of the Library. To do 217 | this, you must alter all the notices that refer to this License, so 218 | that they refer to the ordinary GNU General Public License, version 2, 219 | instead of to this License. (If a newer version than version 2 of the 220 | ordinary GNU General Public License has appeared, then you can specify 221 | that version instead if you wish.) Do not make any other change in 222 | these notices. 223 | ^L 224 | Once this change is made in a given copy, it is irreversible for 225 | that copy, so the ordinary GNU General Public License applies to all 226 | subsequent copies and derivative works made from that copy. 227 | 228 | This option is useful when you wish to copy part of the code of 229 | the Library into a program that is not a library. 230 | 231 | 4. You may copy and distribute the Library (or a portion or 232 | derivative of it, under Section 2) in object code or executable form 233 | under the terms of Sections 1 and 2 above provided that you accompany 234 | it with the complete corresponding machine-readable source code, which 235 | must be distributed under the terms of Sections 1 and 2 above on a 236 | medium customarily used for software interchange. 237 | 238 | If distribution of object code is made by offering access to copy 239 | from a designated place, then offering equivalent access to copy the 240 | source code from the same place satisfies the requirement to 241 | distribute the source code, even though third parties are not 242 | compelled to copy the source along with the object code. 243 | 244 | 5. A program that contains no derivative of any portion of the 245 | Library, but is designed to work with the Library by being compiled or 246 | linked with it, is called a "work that uses the Library". Such a 247 | work, in isolation, is not a derivative work of the Library, and 248 | therefore falls outside the scope of this License. 249 | 250 | However, linking a "work that uses the Library" with the Library 251 | creates an executable that is a derivative of the Library (because it 252 | contains portions of the Library), rather than a "work that uses the 253 | library". The executable is therefore covered by this License. 254 | Section 6 states terms for distribution of such executables. 255 | 256 | When a "work that uses the Library" uses material from a header file 257 | that is part of the Library, the object code for the work may be a 258 | derivative work of the Library even though the source code is not. 259 | Whether this is true is especially significant if the work can be 260 | linked without the Library, or if the work is itself a library. The 261 | threshold for this to be true is not precisely defined by law. 262 | 263 | If such an object file uses only numerical parameters, data 264 | structure layouts and accessors, and small macros and small inline 265 | functions (ten lines or less in length), then the use of the object 266 | file is unrestricted, regardless of whether it is legally a derivative 267 | work. (Executables containing this object code plus portions of the 268 | Library will still fall under Section 6.) 269 | 270 | Otherwise, if the work is a derivative of the Library, you may 271 | distribute the object code for the work under the terms of Section 6. 272 | Any executables containing that work also fall under Section 6, 273 | whether or not they are linked directly with the Library itself. 274 | ^L 275 | 6. As an exception to the Sections above, you may also combine or 276 | link a "work that uses the Library" with the Library to produce a 277 | work containing portions of the Library, and distribute that work 278 | under terms of your choice, provided that the terms permit 279 | modification of the work for the customer's own use and reverse 280 | engineering for debugging such modifications. 281 | 282 | You must give prominent notice with each copy of the work that the 283 | Library is used in it and that the Library and its use are covered by 284 | this License. You must supply a copy of this License. If the work 285 | during execution displays copyright notices, you must include the 286 | copyright notice for the Library among them, as well as a reference 287 | directing the user to the copy of this License. Also, you must do one 288 | of these things: 289 | 290 | a) Accompany the work with the complete corresponding 291 | machine-readable source code for the Library including whatever 292 | changes were used in the work (which must be distributed under 293 | Sections 1 and 2 above); and, if the work is an executable linked 294 | with the Library, with the complete machine-readable "work that 295 | uses the Library", as object code and/or source code, so that the 296 | user can modify the Library and then relink to produce a modified 297 | executable containing the modified Library. (It is understood 298 | that the user who changes the contents of definitions files in the 299 | Library will not necessarily be able to recompile the application 300 | to use the modified definitions.) 301 | 302 | b) Use a suitable shared library mechanism for linking with the 303 | Library. A suitable mechanism is one that (1) uses at run time a 304 | copy of the library already present on the user's computer system, 305 | rather than copying library functions into the executable, and (2) 306 | will operate properly with a modified version of the library, if 307 | the user installs one, as long as the modified version is 308 | interface-compatible with the version that the work was made with. 309 | 310 | c) Accompany the work with a written offer, valid for at 311 | least three years, to give the same user the materials 312 | specified in Subsection 6a, above, for a charge no more 313 | than the cost of performing this distribution. 314 | 315 | d) If distribution of the work is made by offering access to copy 316 | from a designated place, offer equivalent access to copy the above 317 | specified materials from the same place. 318 | 319 | e) Verify that the user has already received a copy of these 320 | materials or that you have already sent this user a copy. 321 | 322 | For an executable, the required form of the "work that uses the 323 | Library" must include any data and utility programs needed for 324 | reproducing the executable from it. However, as a special exception, 325 | the materials to be distributed need not include anything that is 326 | normally distributed (in either source or binary form) with the major 327 | components (compiler, kernel, and so on) of the operating system on 328 | which the executable runs, unless that component itself accompanies 329 | the executable. 330 | 331 | It may happen that this requirement contradicts the license 332 | restrictions of other proprietary libraries that do not normally 333 | accompany the operating system. Such a contradiction means you cannot 334 | use both them and the Library together in an executable that you 335 | distribute. 336 | ^L 337 | 7. You may place library facilities that are a work based on the 338 | Library side-by-side in a single library together with other library 339 | facilities not covered by this License, and distribute such a combined 340 | library, provided that the separate distribution of the work based on 341 | the Library and of the other library facilities is otherwise 342 | permitted, and provided that you do these two things: 343 | 344 | a) Accompany the combined library with a copy of the same work 345 | based on the Library, uncombined with any other library 346 | facilities. This must be distributed under the terms of the 347 | Sections above. 348 | 349 | b) Give prominent notice with the combined library of the fact 350 | that part of it is a work based on the Library, and explaining 351 | where to find the accompanying uncombined form of the same work. 352 | 353 | 8. You may not copy, modify, sublicense, link with, or distribute 354 | the Library except as expressly provided under this License. Any 355 | attempt otherwise to copy, modify, sublicense, link with, or 356 | distribute the Library is void, and will automatically terminate your 357 | rights under this License. However, parties who have received copies, 358 | or rights, from you under this License will not have their licenses 359 | terminated so long as such parties remain in full compliance. 360 | 361 | 9. You are not required to accept this License, since you have not 362 | signed it. However, nothing else grants you permission to modify or 363 | distribute the Library or its derivative works. These actions are 364 | prohibited by law if you do not accept this License. Therefore, by 365 | modifying or distributing the Library (or any work based on the 366 | Library), you indicate your acceptance of this License to do so, and 367 | all its terms and conditions for copying, distributing or modifying 368 | the Library or works based on it. 369 | 370 | 10. Each time you redistribute the Library (or any work based on the 371 | Library), the recipient automatically receives a license from the 372 | original licensor to copy, distribute, link with or modify the Library 373 | subject to these terms and conditions. You may not impose any further 374 | restrictions on the recipients' exercise of the rights granted herein. 375 | You are not responsible for enforcing compliance by third parties with 376 | this License. 377 | ^L 378 | 11. If, as a consequence of a court judgment or allegation of patent 379 | infringement or for any other reason (not limited to patent issues), 380 | conditions are imposed on you (whether by court order, agreement or 381 | otherwise) that contradict the conditions of this License, they do not 382 | excuse you from the conditions of this License. If you cannot 383 | distribute so as to satisfy simultaneously your obligations under this 384 | License and any other pertinent obligations, then as a consequence you 385 | may not distribute the Library at all. For example, if a patent 386 | license would not permit royalty-free redistribution of the Library by 387 | all those who receive copies directly or indirectly through you, then 388 | the only way you could satisfy both it and this License would be to 389 | refrain entirely from distribution of the Library. 390 | 391 | If any portion of this section is held invalid or unenforceable under 392 | any particular circumstance, the balance of the section is intended to 393 | apply, and the section as a whole is intended to apply in other 394 | circumstances. 395 | 396 | It is not the purpose of this section to induce you to infringe any 397 | patents or other property right claims or to contest validity of any 398 | such claims; this section has the sole purpose of protecting the 399 | integrity of the free software distribution system which is 400 | implemented by public license practices. Many people have made 401 | generous contributions to the wide range of software distributed 402 | through that system in reliance on consistent application of that 403 | system; it is up to the author/donor to decide if he or she is willing 404 | to distribute software through any other system and a licensee cannot 405 | impose that choice. 406 | 407 | This section is intended to make thoroughly clear what is believed to 408 | be a consequence of the rest of this License. 409 | 410 | 12. If the distribution and/or use of the Library is restricted in 411 | certain countries either by patents or by copyrighted interfaces, the 412 | original copyright holder who places the Library under this License 413 | may add an explicit geographical distribution limitation excluding those 414 | countries, so that distribution is permitted only in or among 415 | countries not thus excluded. In such case, this License incorporates 416 | the limitation as if written in the body of this License. 417 | 418 | 13. The Free Software Foundation may publish revised and/or new 419 | versions of the Lesser General Public License from time to time. 420 | Such new versions will be similar in spirit to the present version, 421 | but may differ in detail to address new problems or concerns. 422 | 423 | Each version is given a distinguishing version number. If the Library 424 | specifies a version number of this License which applies to it and 425 | "any later version", you have the option of following the terms and 426 | conditions either of that version or of any later version published by 427 | the Free Software Foundation. If the Library does not specify a 428 | license version number, you may choose any version ever published by 429 | the Free Software Foundation. 430 | ^L 431 | 14. If you wish to incorporate parts of the Library into other free 432 | programs whose distribution conditions are incompatible with these, 433 | write to the author to ask for permission. For software which is 434 | copyrighted by the Free Software Foundation, write to the Free 435 | Software Foundation; we sometimes make exceptions for this. Our 436 | decision will be guided by the two goals of preserving the free status 437 | of all derivatives of our free software and of promoting the sharing 438 | and reuse of software generally. 439 | 440 | NO WARRANTY 441 | 442 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 443 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 444 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 445 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 446 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 447 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 448 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 449 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 450 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 451 | 452 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 453 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 454 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 455 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 456 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 457 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 458 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 459 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 460 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 461 | DAMAGES. 462 | 463 | END OF TERMS AND CONDITIONS 464 | ^L 465 | How to Apply These Terms to Your New Libraries 466 | 467 | If you develop a new library, and you want it to be of the greatest 468 | possible use to the public, we recommend making it free software that 469 | everyone can redistribute and change. You can do so by permitting 470 | redistribution under these terms (or, alternatively, under the terms 471 | of the ordinary General Public License). 472 | 473 | To apply these terms, attach the following notices to the library. 474 | It is safest to attach them to the start of each source file to most 475 | effectively convey the exclusion of warranty; and each file should 476 | have at least the "copyright" line and a pointer to where the full 477 | notice is found. 478 | 479 | 480 | Copyright (C) 2005 Keyphrene - Vincent Jaulin 481 | 482 | This library is free software; you can redistribute it and/or 483 | modify it under the terms of the GNU Lesser General Public 484 | License as published by the Free Software Foundation; either 485 | version 2 of the License, or (at your option) any later version. 486 | 487 | This library is distributed in the hope that it will be useful, 488 | but WITHOUT ANY WARRANTY; without even the implied warranty of 489 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 490 | Lesser General Public License for more details. 491 | 492 | You should have received a copy of the GNU Lesser General Public 493 | License along with this library; if not, write to the Free Software 494 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 495 | 496 | Also add information on how to contact you by electronic and paper 497 | mail. 498 | 499 | You should also get your employer (if you work as a programmer) or 500 | your 501 | school, if any, to sign a "copyright disclaimer" for the library, if 502 | necessary. Here is a sample; alter the names: 503 | 504 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 505 | library `Frob' (a library for tweaking knobs) written by James 506 | Random Hacker. 507 | 508 | , 1 April 1990 509 | Ty Coon, President of Vice 510 | 511 | That's all there is to it! 512 | 513 | 514 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2012-04-27 Tristan de Cacqueray 2 | 3 | * src/session.c: 4 | - Add userauth_agent for ssh-agent based authentication 5 | 6 | 2011-07-22 Sofian Brabez 7 | 8 | * New upstream release 9 | * src/channel.c: 10 | - Replace MY_BEGIN_ALLOW_THREAD macro by PY_BEGIN_ALLOW_THREAD 11 | * src/session.c, libssh2/session.py: 12 | - Add support for keyboard interactive autentication 13 | * tests/ 14 | - Add a test suite 15 | 16 | 2010-02-09 Sofian Brabez 17 | 18 | * First release 19 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | ========= 2 | pylibssh2 3 | ========= 4 | 5 | .. Generate an HTML page with "rst2html.py INSTALL > install.html" 6 | .. rst2html.py is part of the docutils software suite. 7 | 8 | .. contents:: **Index** 9 | .. sectnum:: 10 | 11 | 12 | Prerequisites 13 | ============= 14 | 15 | Here is the list of prerequisite software to run pylibssh2. The versions are 16 | the ones I develop with. It may work with earlier versions, but I can't 17 | guaranty anything. 18 | 19 | * `libssh2 `_ 1.2.8+ 20 | * `python `_ 2.6+ 21 | 22 | Install the software 23 | ==================== 24 | 25 | Get the latest version of `pylibssh2`_. 26 | 27 | .. _ `pylibssh2`: http://pypi.python.org/packages/source/p/pylibssh2/ 28 | 29 | Untar the tarball in the directory of your choice:: 30 | 31 | $ tar zxvf pylibssh2-{version}.tar.gz 32 | 33 | Now enter in the pylibssh2-{version} directory. 34 | 35 | Run the following command:: 36 | 37 | # python setup.py install 38 | 39 | or 40 | 41 | $ sudo python setup.py install 42 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS ChangeLog COPYING INSTALL README 2 | recursive-include src *.c *.h 3 | recursive-include examples *.py 4 | recursive-include tests *.py 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | TARGET=libssh2 21 | PY_TARGET=py${TARGET} 22 | DEBIAN_TARGET=python-libssh2 23 | 24 | build: clean 25 | python setup.py clean 26 | python setup.py build --force 27 | 28 | install: build 29 | sudo python setup.py install 30 | 31 | installdeb: 32 | sudo dpkg -i ../${DEBIAN_TARGET}*.deb 33 | 34 | dist: 35 | python setup.py sdist --format=gztar 36 | 37 | deb: 38 | dpkg-buildpackage -tc 39 | 40 | doc: 41 | epydoc --no-private -n ${PY_TARGET} -o doc ${TARGET} 42 | 43 | test: build 44 | python setup.py test 45 | 46 | clean: 47 | rm -rf build dist 48 | rm -rf MANIFEST *.egg-info 49 | rm -rf ${PY_TARGET}/*pyc 50 | 51 | cleandoc: 52 | rm -rf doc 53 | 54 | cleandeb: 55 | rm -rf ../*.deb ../*.dsc ../*.tar.gz ../*.changes 56 | 57 | distclean: clean cleandoc cleandeb 58 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ========= 2 | pylibssh2 3 | ========= 4 | 5 | :libssh2: Python module 6 | :Copyright: Keyphrene, Wallix 7 | :License: LGPL 8 | :Homepage: http://github.com/wallix/pylibssh2 9 | 10 | pylibssh2 1.0.2 11 | ================ 12 | 13 | 1.0.0 release, may 2010 14 | 1.0.1 release, july 2011 15 | 1.0.2 release, apr 2012 16 | 1.0.3 release, july 2012 17 | 18 | What 19 | ---- 20 | 21 | pylibssh2 is a python binding for libssh2 library, it was forked and rewrote 22 | from scratch using old org.keyphrene (http://sourceforge.net/projects/orgkeyphrene/) 23 | bindings. 24 | 25 | Sofian Brabez wrote this extension at Wallix (http://wallix.com) to provide an easy 26 | way to manage SSH2 connection through libssh2 library in python. 27 | 28 | This is a C extension module to provide a high level python API. libssh2 API is 29 | fairy well respected and export into a python API. 30 | 31 | Packaging and API is documented with epydoc format. 32 | 33 | Requirements 34 | ------------ 35 | 36 | - python 2.6+ 37 | (older version before 2.5 aren't supported and not recommended) 38 | - libssh2 1.2.1+ 39 | (older version after 0.18 can works too) 40 | 41 | Linux Debian/Ubuntu:: 42 | 43 | sudo aptitude install python2.6 python2.6-dev libssh2-1 libssh2-1-dev 44 | 45 | FreeBSD:: 46 | 47 | sudo make -C /usr/ports/lang/python install clean 48 | sudo make -C /usr/ports/security/libssh2/ install clean 49 | 50 | License 51 | ------- 52 | 53 | Old parts from Keyphrene.org are licensied against GNU Lesser GPL (LGPL) and all 54 | new and rewritten parts from Wallix.com are licensied against LGPL License too. 55 | 56 | Portability 57 | ----------- 58 | 59 | This is developed and tested mostly on Linux, though it should support others posix 60 | systesm. 61 | 62 | Bugs & Support 63 | --------------- 64 | 65 | Bug tracker is available at 66 | 67 | http://github.com/wallix/pylibssh2/issues 68 | 69 | Get the source code 70 | 71 | git clone http://github.com/wallix/pylibssh2.git 72 | 73 | Browse the source code at 74 | 75 | http://github.com/wallix/pylibssh2.git 76 | 77 | Download tarballs at 78 | 79 | http://pypi.python.org/packages/source/p/pylibssh2/ 80 | 81 | 82 | Example 83 | ------- 84 | 85 | These following examples are located in examples/ directory. 86 | 87 | :scp_upload.py: 88 | dummy version of scp upload file transfer. 89 | 90 | :sftp_listdir.py: 91 | this example show how to list remote directories through 92 | SFTP protocol. 93 | 94 | :ssh_exec.py: 95 | this example show how to execute a SSH remote command execution. 96 | 97 | :ssh.py: 98 | this example demonstrate how implement a partial ssh client to get a remote 99 | shell. 100 | 101 | :ssh_x11.py: 102 | this example demonstrate how implement a X11 forwarding client. 103 | 104 | Documentation 105 | ------------- 106 | 107 | API documentation can be generated with epydoc 108 | with following command line:: 109 | 110 | epydoc --no-private -n pylibssh2 -o doc libssh2 111 | 112 | or 113 | 114 | make doc 115 | 116 | Install 117 | ------- 118 | 119 | See the INSTALL file for installation instructions. 120 | 121 | Don't hesitate to reports bugs and submit patches, or just mail author. 122 | -------------------------------------------------------------------------------- /debian/README.Debian: -------------------------------------------------------------------------------- 1 | The Debian Package python-libssh2 2 | --------------------------------- 3 | 4 | Comments regarding the Package 5 | 6 | -- Sofian Brabez Thu, 26 Nov 2009 23:10:49 +0100 7 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pylibssh2 (1.0.3) unstable; urgency=low 2 | 3 | * src/channel.c, libssh2/channel.py: 4 | - Add support for non blocking mode 5 | - Add read_stderr binding 6 | * src/session.c, libssh2/session.py: 7 | - Add support for non blocking mode 8 | - Add setblocking, getblocking, blockdirections binding 9 | * examples/ssh_exec2.py: 10 | - Add example to demonstrate non blocking capabilities. 11 | * Thanks goes to Morian, cvss and aaloksood 12 | 13 | -- Tristan de Cacqueray Tue, 10 Jul 2012 11:51:42 +0200 14 | 15 | pylibssh2 (1.0.2) unstable; urgency=low 16 | 17 | * src/session.c: 18 | - Add userauth_agent for ssh-agent based authentication 19 | 20 | -- Tristan de Cacqueray Fri, 27 Apr 2012 11:11:42 +0200 21 | 22 | pylibssh2 (1.0.1) unstable; urgency=low 23 | 24 | * New upstream release 25 | * src/channel.c: 26 | - Replace MY_BEGIN_ALLOW_THREAD macro by PY_BEGIN_ALLOW_THREAD 27 | * src/session.c, libssh2/session.py: 28 | - Add support for keyboard interactive autentication 29 | * tests/ 30 | - Add a test suite 31 | 32 | -- Sofian Brabez Tue, 11 Jul 2011 15:58:49 +0100 33 | 34 | pylibssh2 (1.0.0) unstable; urgency=low 35 | 36 | * Initial Release. 37 | 38 | -- Sofian Brabez Tue, 8 Dec 2009 17:10:49 +0100 39 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: pylibssh2 2 | Section: libs 3 | Priority: extra 4 | Maintainer: Sofian Brabez 5 | Build-Depends: cdbs (>= 0.4.49), libssh2-1-dev, python-all-dev, python-support 6 | Standards-Version: 3.8.1 7 | 8 | Package: python-libssh2 9 | Architecture: any 10 | Homepage: http://pypi.python.org/pypi/pylibssh2 11 | Depends: ${shlibs:Depends}, ${misc:Depends} 12 | Description: Python binding for libssh2 library 13 | Python binding for libssh2 library 14 | wwww: http://pypi.python.org/pypi/pylibssh2 15 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This package was debianized by Sofian Brabez on 2 | Thu, 26 Nov 2009 23:10:49 +0100. 3 | 4 | It was downloaded from http://pypi.python.org/pypi/pylibssh2 5 | 6 | Upstream Author(s): 7 | 8 | Sofian Brabez 9 | 10 | Copyright: 11 | 12 | Copyright (C) 2009 Wallix Inc. 13 | 14 | License: 15 | 16 | Redistribution and use in source and binary forms, with or without 17 | modification, are permitted under the terms of the BSD License. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | SUCH DAMAGE. 30 | 31 | On Debian systems, the complete text of the BSD License can be 32 | found in `/usr/share/common-licenses/BSD'. 33 | 34 | The Debian packaging is: 35 | 36 | Copyright (C) 2009 Sofian Brabez 37 | 38 | and is licensed under the GPL version 3, 39 | see `/usr/share/common-licenses/GPL-3'. 40 | 41 | 42 | 43 | # Please also look if there are files or directories which have a 44 | # different copyright/license attached and list them here. 45 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | -------------------------------------------------------------------------------- /debian/pycompat: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /debian/python-libssh2.examples: -------------------------------------------------------------------------------- 1 | examples/*.py 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # export DH_VERBOSE=1 3 | 4 | DEB_PYTHON_SYSTEM := pysupport 5 | DEB_DH_STRIP_ARGS := --dbg-package=python-libssh2 6 | 7 | include /usr/share/cdbs/1/rules/buildcore.mk 8 | include /usr/share/cdbs/1/rules/debhelper.mk 9 | include /usr/share/cdbs/1/rules/simple-patchsys.mk 10 | include /usr/share/cdbs/1/class/python-distutils.mk 11 | 12 | 13 | clean:: 14 | rm -rf build 15 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | http://pypi.python.org/packages/source/p/pylibssh2/pylibssh2-(.*)\.tar\.gz 3 | -------------------------------------------------------------------------------- /examples/scp_upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import socket, sys 22 | 23 | import libssh2 24 | 25 | usage = """Do a SCP send with username@hostname:/remote_path/ 26 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 27 | 28 | class MySCPClient: 29 | def __init__(self, hostname, username, password, port=22): 30 | self.hostname = hostname 31 | self.username = username 32 | self.password = password 33 | self.port = port 34 | self._prepare_sock() 35 | 36 | def _prepare_sock(self): 37 | try: 38 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 39 | self.sock.connect((self.hostname, self.port)) 40 | self.sock.setblocking(1) 41 | except Exception, e: 42 | print "SockError: Can't connect socket to %s:%d" % (self.hostname, self.port) 43 | print e 44 | 45 | try: 46 | self.session = libssh2.Session() 47 | self.session.set_banner() 48 | self.session.startup(self.sock) 49 | self.session.userauth_password(self.username, self.password) 50 | except Exception, e: 51 | print "SSHError: Can't startup session" 52 | print e 53 | 54 | def send(self, remote_path, mode=0644): 55 | datas="" 56 | f=file(remote_path, "rb") 57 | while True: 58 | data = f.readline() 59 | if len(data) == 0: 60 | break 61 | else: 62 | datas += data 63 | file_size = len(datas) 64 | channel = self.session.scp_send(remote_path, mode, file_size) 65 | channel.write(datas) 66 | channel.close() 67 | 68 | def __del__(self): 69 | self.session.close() 70 | self.sock.close() 71 | 72 | if __name__ == '__main__' : 73 | if len(sys.argv) == 1: 74 | print usage 75 | sys.exit(1) 76 | myscp = MySCPClient( 77 | hostname=sys.argv[1], 78 | username=sys.argv[2], 79 | password=sys.argv[3] 80 | ) 81 | myscp.send(sys.argv[4]) 82 | -------------------------------------------------------------------------------- /examples/sftp_listdir.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import socket, sys 22 | 23 | import libssh2 24 | 25 | usage = """Do a SFTP file listing of with username@hostname 26 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 27 | 28 | class MySFTPClient: 29 | def __init__(self, hostname, username, password, port=22): 30 | self.hostname = hostname 31 | self.username = username 32 | self.password = password 33 | self.port = port 34 | self._prepare_sock() 35 | 36 | def _prepare_sock(self): 37 | try: 38 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 39 | self.sock.connect((self.hostname, self.port)) 40 | self.sock.setblocking(1) 41 | except Exception, e: 42 | print "SockError: Can't connect socket to %s:%d" % (self.hostname, self.port) 43 | print e 44 | 45 | try: 46 | self.session = libssh2.Session() 47 | self.session.set_banner() 48 | self.session.startup(self.sock) 49 | self.session.userauth_password(self.username, self.password) 50 | except Exception, e: 51 | print "SSHError: Can't startup session" 52 | print e 53 | 54 | # use low level layer because we don't yet provide High layer for sftp 55 | self.sftp = self.session._session.sftp_init() 56 | 57 | def listdir(self, remote_path='/tmp'): 58 | handle = self.sftp.opendir(remote_path) 59 | if handle: 60 | while True: 61 | data = self.sftp.readdir(handle) 62 | if not data: break 63 | print data 64 | 65 | for file, attribute in self.sftp.listdir(handle): 66 | print file, attribute 67 | 68 | self.sftp.close(handle) 69 | 70 | def __del__(self): 71 | self.session.close() 72 | self.sock.close() 73 | 74 | if __name__ == '__main__' : 75 | if len(sys.argv) == 1: 76 | print usage 77 | sys.exit(1) 78 | mysftp = MySFTPClient( 79 | hostname=sys.argv[1], 80 | username=sys.argv[2], 81 | password=sys.argv[3] 82 | ) 83 | mysftp.listdir(sys.argv[4]) 84 | -------------------------------------------------------------------------------- /examples/ssh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import atexit 22 | import select, socket, sys 23 | import tty, termios 24 | 25 | import libssh2 26 | 27 | DEBUG=False 28 | 29 | usage = """Do a SSH connection with username@hostname 30 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 31 | 32 | class MySSHClient: 33 | def __init__(self, hostname, username, password, port=22): 34 | self.hostname = hostname 35 | self.username = username 36 | self.password = password 37 | self.port = port 38 | self._prepare_sock() 39 | 40 | def _prepare_sock(self): 41 | try: 42 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 43 | self.sock.connect((self.hostname, self.port)) 44 | self.sock.setblocking(1) 45 | except Exception, e: 46 | print "SockError: Can't connect socket to %s:%d" % (self.hostname, self.port) 47 | print e 48 | 49 | try: 50 | self.session = libssh2.Session() 51 | self.session.set_banner() 52 | 53 | self.session.startup(self.sock) 54 | 55 | # authentication 56 | auth_list = self.session.userauth_list(self.username) 57 | if DEBUG: 58 | sys.stdout.write("Authentication that can continue %s\r\n" % auth_list) 59 | self.session.userauth_password(self.username, self.password) 60 | 61 | except Exception, e: 62 | print "SSHError: Can't startup session" 63 | print e 64 | 65 | def run(self): 66 | 67 | try: 68 | # open channel 69 | channel = self.session.open_session() 70 | 71 | # request pty 72 | channel.pty('vt100') 73 | 74 | # request shell 75 | channel.shell() 76 | channel.setblocking(0) 77 | 78 | # loop 79 | while True: 80 | data_to_disp = channel.poll_read(1) 81 | if data_to_disp > 0: 82 | data = channel.read(1024) 83 | if data is not None: 84 | sys.stdout.write(data) 85 | else: 86 | break 87 | sys.stdout.flush() 88 | 89 | r,w,x = select.select([fd],[],[],0.01) 90 | if sys.stdin.fileno() in r: 91 | data = sys.stdin.read(1).replace('\n','\r\n') 92 | channel.write(data) 93 | 94 | except Exception,e: 95 | print e 96 | finally: 97 | channel.close() 98 | 99 | 100 | def __del__(self): 101 | self.session.close() 102 | self.sock.close() 103 | 104 | if __name__ == '__main__' : 105 | if len(sys.argv) == 1: 106 | print usage 107 | sys.exit(1) 108 | 109 | # save terminal settings 110 | fd = sys.stdin.fileno() 111 | old_settings = termios.tcgetattr(fd) 112 | 113 | # enable raw mode 114 | tty.setraw(fd) 115 | 116 | myssh = MySSHClient(sys.argv[1],sys.argv[2], sys.argv[3]) 117 | myssh.run() 118 | 119 | # restore terminal settings 120 | atexit.register( 121 | termios.tcsetattr, 122 | sys.stdin.fileno(), termios.TCSADRAIN, old_settings 123 | ) 124 | -------------------------------------------------------------------------------- /examples/ssh_exec.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import socket, sys 22 | 23 | import libssh2 24 | 25 | DEBUG=False 26 | 27 | usage = """Do a SSH remote command with username@hostname 28 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 29 | 30 | def my_print(args): 31 | if DEBUG: print(args) 32 | 33 | class SSHRemoteClient(object): 34 | def __init__(self, hostname, username, password, port=22): 35 | self.username = username 36 | self.password = password 37 | self.hostname = hostname 38 | self.port = port 39 | 40 | self.session = libssh2.Session() 41 | self.session.set_banner() 42 | 43 | try: 44 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 45 | sock.connect((self.hostname,self.port)) 46 | self.session.startup(sock) 47 | my_print(self.session.last_error()) 48 | self.session.userauth_password(self.username,self.password) 49 | my_print(self.session.last_error()) 50 | except Exception, e: 51 | print str(e) 52 | raise Exception, self.session.last_error() 53 | 54 | self.channel = self.session.open_session() 55 | my_print(self.session.last_error()) 56 | 57 | def execute(self, command="uname -a"): 58 | buffer = 4096 59 | rc = self.channel.execute(command) 60 | my_print(rc) 61 | while True: 62 | data = self.channel.read(buffer) 63 | if data == '' or data is None: break 64 | my_print(type(data)) 65 | print data.strip() 66 | 67 | self.channel.close() 68 | 69 | def __del__(self): 70 | self.session.close() 71 | my_print(self.session.last_error()) 72 | 73 | if __name__ == '__main__': 74 | try: 75 | if len(sys.argv) == 1: 76 | print usage 77 | sys.exit(1) 78 | src = SSHRemoteClient(sys.argv[1], sys.argv[2], sys.argv[3]) 79 | src.execute(sys.argv[4]) 80 | except Exception, e: 81 | print str(e) 82 | except KeyboardInterrupt, e: 83 | sys.exit(1) 84 | -------------------------------------------------------------------------------- /examples/ssh_exec2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | import socket 5 | from select import select 6 | 7 | import libssh2 8 | 9 | 10 | DEBUG = False 11 | 12 | usage = """Do a SSH remote command with username@hostname 13 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 14 | 15 | 16 | def my_print(args): 17 | if DEBUG: print(args) 18 | 19 | class SSHRemoteClientNonBlocking(object): 20 | LIBSSH2_ERROR_EAGAIN= -37 21 | 22 | def __init__(self, hostname, username, password, port=22): 23 | self.username = username 24 | self.password = password 25 | self.hostname = hostname 26 | self.port = port 27 | 28 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 29 | self.sock.setblocking(1) 30 | self.sock.connect_ex((self.hostname, self.port)) 31 | self.sock.setblocking(0) 32 | 33 | self.session = libssh2.Session() 34 | self.session.setblocking(0) 35 | 36 | def _wait_select(self): 37 | ''' 38 | Find out from libssh2 if its blocked on read or write and wait accordingly 39 | Return immediately if libssh2 is not blocked 40 | ''' 41 | blockdir = self.session.blockdirections() 42 | if blockdir == 0: 43 | # return if not blocked 44 | return 45 | 46 | readfds = [self.sock] if (blockdir & 01) else [] 47 | writefds = [self.sock] if (blockdir & 02) else [] 48 | select(readfds, writefds, []) 49 | return 50 | 51 | 52 | def startup(self): 53 | count = 1 54 | ret = self.session.startup(self.sock) 55 | while ret==self.LIBSSH2_ERROR_EAGAIN: 56 | self._wait_select() 57 | count += 1 58 | ret = self.session.startup(self.sock) 59 | 60 | my_print("startup count is %s" %count) 61 | my_print("sess startup ret is %s" %ret) 62 | 63 | 64 | def auth(self): 65 | count = 1 66 | ret = self.session.userauth_password(self.username, self.password) 67 | while ret == self.LIBSSH2_ERROR_EAGAIN: 68 | self._wait_select() 69 | count += 1 70 | ret = self.session.userauth_password(self.username, self.password) 71 | 72 | my_print("userauth count is %s" %count) 73 | my_print("userauth pass ret is %s" %ret) 74 | 75 | def open_channel(self): 76 | self.chan = self.session.open_session() 77 | count = 1 78 | while self.chan == None: 79 | count += 1 80 | self._wait_select() 81 | self.chan = self.session.open_session() 82 | 83 | my_print("open channel count is %s" %count) 84 | 85 | count = 1 86 | ret = self.chan.pty() 87 | while ret == self.LIBSSH2_ERROR_EAGAIN: 88 | count += 1 89 | self._wait_select() 90 | ret = self.chan.pty() 91 | 92 | my_print("channel pty count is %s" %count) 93 | my_print("channel pty ret is %s" %ret) 94 | 95 | def execute(self, cmd): 96 | count = 1 97 | ret = self.chan.execute(cmd) 98 | while ret == self.LIBSSH2_ERROR_EAGAIN: 99 | count += 1 100 | self._wait_select() 101 | ret = self.chan.execute(cmd) 102 | 103 | my_print("execute count is %s" %count) 104 | my_print("execute ret is %s" %ret) 105 | 106 | while not self.chan.eof(): 107 | self._wait_select() 108 | data1 = self.chan.read_ex() 109 | while data1[0] > 0: 110 | my_print('Received data') 111 | print data1[1] 112 | data1 = self.chan.read_ex() 113 | 114 | 115 | def __del__(self): 116 | count = 1 117 | ret = self.session.close() 118 | while ret == self.LIBSSH2_ERROR_EAGAIN: 119 | count += 1 120 | self._wait_select() 121 | ret = self.session.close(cmd) 122 | 123 | my_print('session close count is %s' %count) 124 | 125 | 126 | if __name__ == '__main__': 127 | try: 128 | if len(sys.argv) == 1: 129 | print usage 130 | sys.exit(1) 131 | src = SSHRemoteClientNonBlocking(sys.argv[1], sys.argv[2], sys.argv[3]) 132 | src.startup() 133 | src.auth() 134 | src.open_channel() 135 | src.execute(sys.argv[4]) 136 | except Exception, e: 137 | print str(e) 138 | except KeyboardInterrupt, e: 139 | sys.exit(1) 140 | -------------------------------------------------------------------------------- /examples/ssh_publickey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import atexit 22 | import select, socket, sys 23 | import tty, termios 24 | import os 25 | 26 | import libssh2 27 | 28 | DEBUG=True 29 | 30 | usage = """Do a SSH connection with username@hostname using a public/private key 31 | Usage: %s [ []]""" % __file__[__file__.rfind('/')+1:] 32 | 33 | class MySSHClient: 34 | def __init__(self, hostname, username, private_key, password=None, public_key=None, port=22): 35 | self.hostname = hostname 36 | self.username = username 37 | self.private_key = os.path.expanduser(private_key) 38 | self.password = password 39 | if not public_key is None: 40 | self.public_key = os.path.expanduser(public_key) 41 | else: 42 | self.public_key = public_key 43 | self.port = port 44 | self._prepare_sock() 45 | 46 | def _prepare_sock(self): 47 | try: 48 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 49 | self.sock.connect((self.hostname, self.port)) 50 | self.sock.setblocking(1) 51 | except Exception, e: 52 | print "SockError: Can't connect socket to %s:%d" % (self.hostname, self.port) 53 | print e 54 | 55 | try: 56 | self.session = libssh2.Session() 57 | # To activable full debug, uncomment the following line 58 | # self.session.set_trace(0xff) 59 | self.session.set_banner() 60 | 61 | self.session.startup(self.sock) 62 | # authentication 63 | self.session.userauth_publickey_fromfile(self.username, self.public_key, self.private_key, self.password) 64 | 65 | except Exception, e: 66 | print "SSHError: Can't startup session" 67 | raise e 68 | 69 | def run(self): 70 | 71 | try: 72 | # open channel 73 | channel = self.session.open_session() 74 | 75 | # request pty 76 | channel.pty('vt100') 77 | 78 | # request shell 79 | channel.shell() 80 | channel.setblocking(0) 81 | 82 | # loop 83 | while True: 84 | data_to_disp = channel.poll_read(1) 85 | if data_to_disp > 0: 86 | data = channel.read(1024) 87 | if data is not None: 88 | sys.stdout.write(data) 89 | else: 90 | break 91 | sys.stdout.flush() 92 | 93 | r,w,x = select.select([fd],[],[],0.01) 94 | if sys.stdin.fileno() in r: 95 | data = sys.stdin.read(1).replace('\n','\r\n') 96 | channel.write(data) 97 | 98 | except (EOFError, TypeError): 99 | # Print a newline (in case user was sitting at prompt) 100 | print('') 101 | except Exception as e: 102 | print e 103 | finally: 104 | channel.close() 105 | 106 | 107 | def __del__(self): 108 | self.session.close() 109 | self.sock.close() 110 | 111 | if __name__ == '__main__' : 112 | 113 | def argv_or(position, default): 114 | if len(sys.argv) > position: 115 | return sys.argv[position] 116 | else: 117 | return default 118 | 119 | if len(sys.argv) == 1: 120 | print usage 121 | sys.exit(1) 122 | 123 | # save terminal settings 124 | fd = sys.stdin.fileno() 125 | old_settings = termios.tcgetattr(fd) 126 | 127 | # enable raw mode 128 | 129 | try: 130 | myssh = MySSHClient(argv_or(1, "localhost"), argv_or(2, "root"), argv_or(3, "~/.ssh/id_dsa"), argv_or(4, None), argv_or(5, None)) 131 | tty.setraw(fd) 132 | myssh.run() 133 | 134 | finally: 135 | print '' 136 | # restore terminal settings 137 | atexit.register( 138 | termios.tcsetattr, 139 | sys.stdin.fileno(), termios.TCSADRAIN, old_settings 140 | ) 141 | -------------------------------------------------------------------------------- /examples/ssh_x11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # pylibssh2 - python bindings for libssh2 library 4 | # 5 | # Copyright (C) 2010 Wallix Inc. 6 | # 7 | # This library is free software; you can redistribute it and/or modify it 8 | # under the terms of the GNU Lesser General Public License as published by the 9 | # Free Software Foundation; either version 2.1 of the License, or (at your 10 | # option) any later version. 11 | # 12 | # This library is distributed in the hope that it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | # details. 16 | # 17 | # You should have received a copy of the GNU Lesser General Public License 18 | # along with this library; if not, write to the Free Software Foundation, Inc., 19 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | # 21 | import atexit 22 | #import fcntl, signal, struct 23 | import os 24 | import select, sys 25 | import subprocess 26 | from socket import socket, AF_INET, AF_UNIX, SOCK_STREAM, SHUT_RDWR 27 | import tty, termios 28 | 29 | import libssh2 30 | from libssh2 import SessionException, ChannelException 31 | 32 | usage = """Do a X11 SSH connection with username@hostname 33 | Usage: %s """ % __file__[__file__.rfind('/')+1:] 34 | 35 | def remove_node(elem): 36 | x11_channels.remove(elem) 37 | 38 | def session_shutdown(session): 39 | session.close() 40 | del session 41 | 42 | def raw_mode(fd): 43 | tty.setraw(fd) 44 | 45 | def normal_mode(fd): 46 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 47 | 48 | def x11_callback(session, channel, shost, sport, abstract): 49 | display = os.environ["DISPLAY"] 50 | display_port = display[display.index(":")+1] 51 | _path_unix_x = "/tmp/.X11-unix/X%s" % display_port 52 | if display[:5] == "unix:" or display[0] == ':': 53 | sock = socket(AF_UNIX, SOCK_STREAM) 54 | sock.connect(_path_unix_x) 55 | channel.setblocking(0) 56 | x11_channels.append((sock, channel)) 57 | 58 | def trace(session): 59 | if DEBUG and session: 60 | session.set_trace( 61 | libssh2.LIBSSH2_TRACE_TRANS| 62 | libssh2.LIBSSH2_TRACE_CONN| 63 | libssh2.LIBSSH2_TRACE_AUTH| 64 | libssh2.LIBSSH2_TRACE_ERROR 65 | ) 66 | 67 | if __name__ == '__main__': 68 | if len(sys.argv) == 1: 69 | print usage 70 | sys.exit(1) 71 | 72 | DEBUG=False 73 | x11_channels = [] 74 | buffsize = 8192 75 | 76 | # save terminal settings 77 | fd = sys.stdin.fileno() 78 | old_settings = termios.tcgetattr(fd) 79 | 80 | hostname = sys.argv[1] 81 | username = sys.argv[2] 82 | password = sys.argv[3] 83 | port = int(sys.argv[4]) 84 | 85 | sock = socket(AF_INET, SOCK_STREAM) 86 | try: 87 | sock.connect((hostname, port)) 88 | sock.setblocking(0) 89 | except Exception, e: 90 | print "Can't connect socket to (%s:%d): %s" % ( 91 | hostname, port, e 92 | ) 93 | sys.exit(1) 94 | 95 | # start session 96 | session = libssh2.Session() 97 | try: 98 | session.set_banner() 99 | # trace session on stderr if DEBUG=True 100 | trace(session) 101 | session.startup(sock) 102 | except SessionException, e: 103 | print "Can't startup session: %s" % e 104 | sys.exit(1) 105 | 106 | # register X11 callback 107 | session.callback_set( 108 | libssh2.LIBSSH2_CALLBACK_X11, 109 | x11_callback 110 | ) 111 | 112 | try: 113 | session.userauth_password(username, password) 114 | except SessionException, e: 115 | print "Failed to authenticate user with %s %s" % ( 116 | username, password 117 | ) 118 | sys.exit(1) 119 | 120 | try: 121 | # open channel 122 | channel = session.open_session() 123 | 124 | # request pty 125 | channel.pty('xterm') 126 | 127 | # parse xauth data 128 | p = subprocess.Popen( 129 | ['xauth','list'], shell=False, stdout=subprocess.PIPE 130 | ) 131 | xauth_data = p.communicate()[0] 132 | auth_protocol, auth_cookie = xauth_data.split()[1:] 133 | 134 | # request X11 forwarding on display 0 135 | channel.x11_req(0, auth_protocol, auth_cookie, 0) 136 | 137 | # request shell 138 | channel.shell() 139 | channel.setblocking(0) 140 | 141 | # enable raw mode 142 | raw_mode(fd) 143 | 144 | while True: 145 | socks = [fd] + [sock for sock, _ in x11_channels] 146 | r, w, x = select.select(socks, [], [], 0.01) 147 | 148 | # reading input from tty channel 149 | status, data = channel.read_ex(buffsize) 150 | if status > 0: 151 | sys.stdout.write(data) 152 | else: 153 | sys.stdout.flush() 154 | 155 | if fd in r: 156 | data = sys.stdin.read(1).replace('\n','\r\n') 157 | channel.write(data) 158 | 159 | for sock, x11_chan in list(x11_channels): 160 | status, data = x11_chan.read_ex(buffsize) 161 | if status > 0: 162 | sock.sendall(data) 163 | 164 | if sock in r: 165 | data = sock.recv(buffsize) 166 | if data is None: 167 | sock.shutdown(SHUT_RDWR) 168 | sock.close() 169 | x11_channels.remove((x11_chan, sock)) 170 | else: 171 | x11_chan.write(data) 172 | 173 | if x11_chan.eof(): 174 | sock.shutdown(SHUT_RDWR) 175 | sock.close() 176 | x11_channels.remove((sock, x11_chan)) 177 | continue 178 | 179 | if channel.eof(): 180 | break 181 | 182 | except ChannelException, e: 183 | print "Channel exception: %s" % e 184 | finally: 185 | channel.close() 186 | 187 | session_shutdown(session) 188 | sock.close() 189 | 190 | # restore terminal settings 191 | atexit.register( 192 | normal_mode, fd 193 | ) 194 | -------------------------------------------------------------------------------- /libssh2/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | __doc__ = """Python binding for libssh2 library""" 21 | 22 | from version import * 23 | 24 | from channel import ChannelException, Channel 25 | from session import SessionException, Session 26 | from sftp import SftpException, Sftp 27 | 28 | __all__ = [ 29 | 'Channel', 30 | 'ChannelException', 31 | 'Session', 32 | 'SessionException', 33 | 'Sftp', 34 | 'SftpException' 35 | ] 36 | 37 | LIBSSH2_TRACE_TRANS = 1<<1 38 | LIBSSH2_TRACE_KEX = 1<<2 39 | LIBSSH2_TRACE_AUTH = 1<<3 40 | LIBSSH2_TRACE_CONN = 1<<4 41 | LIBSSH2_TRACE_SCP = 1<<5 42 | LIBSSH2_TRACE_SFTP = 1<<6 43 | LIBSSH2_TRACE_ERROR = 1<<7 44 | LIBSSH2_TRACE_PUBLICKEY = 1<<8 45 | LIBSSH2_TRACE_SOCKET = 1<<9 46 | 47 | LIBSSH2_CALLBACK_X11 = 4 48 | 49 | LIBSSH2_ERROR_EAGAIN = -37 50 | -------------------------------------------------------------------------------- /libssh2/channel.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | """ 21 | Abstraction for libssh2 L{Channel} object 22 | """ 23 | 24 | class ChannelException(Exception): 25 | """ 26 | Exception raised when L{Channel} actions fails. 27 | """ 28 | pass 29 | 30 | class Channel(object): 31 | """ 32 | Channel object 33 | """ 34 | def __init__(self, _channel): 35 | """ 36 | Creates a new channel object with the given _channel. 37 | 38 | @param _channel: low level channel object 39 | @type _channel: L{_libssh2.Channel} 40 | """ 41 | self._channel = _channel 42 | self.closed = False 43 | self.flushed = False 44 | 45 | def close(self): 46 | """ 47 | Closes the active channel. 48 | 49 | @return: 0 on success, 50 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode) 51 | @rtype: int 52 | """ 53 | self.closed = True 54 | return self._channel.close() 55 | 56 | def wait_closed(self): 57 | """ 58 | Wait for remote channel to ack closing. 59 | 60 | @return: 0 on success, 61 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode), 62 | a negative value on failure 63 | @rtype: int 64 | """ 65 | self.closed = True 66 | return self._channel.wait_closed() 67 | 68 | def eof(self): 69 | """ 70 | Checks if the remote host has sent a EOF status. 71 | 72 | @return: 1 if the remote host has sent EOF otherwise 0 73 | @rtype: int 74 | """ 75 | return self._channel.eof() 76 | 77 | def execute(self, command): 78 | """ 79 | Executes command on the channel. 80 | 81 | @param command: message data 82 | @type command: str 83 | 84 | @return: 0 on success, 85 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode) 86 | @rtype: int 87 | """ 88 | self.closed = True 89 | return self._channel.execute(command) 90 | 91 | def exit_status(self): 92 | """ 93 | Gets the exit code raised by the process running on the remote host. 94 | 95 | @return: the exit status reported by remote host or 0 on failure 96 | @rtype: int 97 | """ 98 | return self._channel.exit_status() 99 | 100 | def flush(self): 101 | """ 102 | Flushs the read buffer on the channel. 103 | 104 | @return: 0 on sucess or negative on failure 105 | @rtype: int 106 | """ 107 | self.flushed = True 108 | return self._channel.flush() 109 | 110 | def poll_read(self, extended): 111 | """ 112 | Checks if data is available on the channel. 113 | 114 | @param extended: if message channel datas is extended 115 | @type extended: int 116 | 117 | @return: 1 when data is available or 0 otherwise 118 | @rtype: int 119 | """ 120 | return self._channel.poll_read(extended) 121 | 122 | def pty(self, term="vt100"): 123 | """ 124 | Requests a pty with term type on the channel. 125 | 126 | @param term: terminal emulation type (vt100, ansi, etc...) 127 | @type term: str 128 | 129 | @return: 0 on success or negative on failure 130 | @rtype: int 131 | """ 132 | return self._channel.pty(term) 133 | 134 | def pty_resize(self, width, height, pixelwidth=0, pixelheight=0): 135 | """ 136 | Requests a pty resize of the channel with given width and height. 137 | 138 | @param width: terminal width in characters 139 | @type width: int 140 | @param height: terminal height in characters 141 | @type height: int 142 | @param pixelwidth: terminal width in pixels 143 | @type pixelwidth: int 144 | @param pixelheight: terminal height in pixels 145 | @type pixelheight: int 146 | 147 | @return: 0 on success, 148 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode) 149 | @rtype: int 150 | """ 151 | return self._channel.pty_resize(width, height, pixelwidth, pixelheight) 152 | 153 | def read(self, size=1024): 154 | """ 155 | Reads size bytes on the channel. 156 | 157 | @param size: size of the buffer storage 158 | @type size: int 159 | 160 | @return: bytes readed, 161 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode), 162 | None if EOF is encoutered 163 | @rtype: str or int or none 164 | """ 165 | return self._channel.read(size) 166 | 167 | def read_stderr(self, size=1024): 168 | """ 169 | Reads size bytes on the channel stderr. 170 | 171 | @param size: size of the buffer storage 172 | @type size: int 173 | 174 | @return: bytes readed, 175 | LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode), 176 | None if EOF is encoutered 177 | @rtype: str or int or none 178 | """ 179 | return self._channel.read_stderr(size) 180 | 181 | def read_ex(self, size=1024, stream_id=0): 182 | """ 183 | Reads size bytes on the channel with given stream_id. 184 | 185 | @param size: size of the buffer storage 186 | @type size: int 187 | 188 | @param stream_id: stream_id of the stream upon which to read 189 | @type size: int 190 | 191 | @return: bytes readed or negative on failure 192 | @rtype: str 193 | """ 194 | return self._channel.read_ex(size, stream_id) 195 | 196 | def send_eof(self): 197 | """ 198 | Sends EOF status on the channel to remote server. 199 | 200 | @return: 0 on success or negative on failure 201 | @rtype: int 202 | """ 203 | self._channel.send_eof() 204 | 205 | def setblocking(self, mode=1): 206 | """ 207 | Sets blocking mode on the channel. Default mode is blocking. 208 | 209 | @param mode: blocking (1) or non blocking (0) mode 210 | @rtype: int 211 | """ 212 | return self._channel.setblocking(mode) 213 | 214 | def setenv(self, name, value): 215 | """ 216 | Sets envrionment variable on the channel. 217 | 218 | @param name: envrionment variable name 219 | @type name: str 220 | @param value: envrionment variable value 221 | @type value: str 222 | 223 | @return: 0 on success or negative on failure 224 | @rtype: int 225 | """ 226 | return self._channel.setenv(name, value) 227 | 228 | def shell(self): 229 | """ 230 | Requests a shell on the channel. 231 | 232 | @return: 0 on success or negative on failure 233 | @rtype: int 234 | """ 235 | return self._channel.shell() 236 | 237 | def window_read(self): 238 | """ 239 | Checks the status of the read window on the channel. 240 | 241 | @param read_avail: window limit to read 242 | @type read_avail: int 243 | @param window_size_initial: window initial size defined 244 | @type window_size_initial: int 245 | 246 | @return: the number of bytes which the remote end may send 247 | without overflowing the window limit 248 | @rtype: int 249 | """ 250 | return self._channel.window_read() 251 | 252 | def window_write(self): 253 | """ 254 | window_write() -> (int, int) 255 | 256 | check the status of the write window. 257 | 258 | 259 | @return windows: the number of bytes which may be safely writen on the 260 | channel without blocking. 261 | @return window_size_initial: as defined by the channel_open request 262 | @rtype (int, int) 263 | """ 264 | return self._channel.window_write() 265 | 266 | def write(self, message): 267 | """ 268 | Writes data on the channel. 269 | 270 | @param message: data to write 271 | @type message: str 272 | 273 | @return: 0 on sucess or failure 274 | @rtype: int 275 | """ 276 | return self._channel.write(message) 277 | 278 | def x11_req(self, single_connection, auth_proto, auth_cookie, display): 279 | """ 280 | Requests a X11 Forwarding on the channel. 281 | 282 | @param single_connection: forward a single connection 283 | @type single_connection: int 284 | @param auth_proto: X11 authentication protocol to use 285 | @type auth_proto: str 286 | @param auth_cookie: the cookie 287 | @type auth_cookie: str 288 | @param display: screen number 289 | @type display: int 290 | 291 | @return: 0 on success or negative on failure 292 | @rtype: int 293 | """ 294 | return self._channel.x11_req(single_connection, auth_proto, auth_cookie, display) 295 | -------------------------------------------------------------------------------- /libssh2/session.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | """ 21 | Abstraction for libssh2 L{Session} object 22 | """ 23 | 24 | import _libssh2 25 | 26 | from channel import Channel 27 | 28 | class SessionException(Exception): 29 | """ 30 | Exception raised when L{Session} actions fails. 31 | """ 32 | pass 33 | 34 | class Session(object): 35 | """ 36 | Session object 37 | """ 38 | def __init__(self): 39 | """ 40 | Create a new session object. 41 | """ 42 | self._session = _libssh2.Session() 43 | 44 | def callback_set(self, callback_type, callback): 45 | """ 46 | Sets callback on the session. 47 | 48 | @param callback_type: value of libssh2.LIBSSH2_CALLBACK_* constant 49 | @type callback_set: int 50 | @param callback: a callback Python object 51 | @type callback: function 52 | """ 53 | self._session.callback_set(callback_type, callback) 54 | 55 | def close(self, reason="Disconnect"): 56 | """ 57 | Closes the session. 58 | 59 | @param reason: human readable reason for disconnection 60 | @type reason: str 61 | 62 | @return: 0 on success or negative on failure 63 | @rtype: int 64 | """ 65 | return self._session.close(reason) 66 | 67 | def direct_tcpip(self, host, port, shost, sport): 68 | """ 69 | Tunnels a TCP connection through the session. 70 | 71 | @param host: remote host 72 | @type host: str 73 | @param port: remote port 74 | @type port: int 75 | @param shost: local host 76 | @type shost: str 77 | @param sport: local port 78 | @type sport: int 79 | 80 | @return: new opened L{Channel} 81 | @rtype: L{Channel} 82 | """ 83 | return self._session.direct_tcpip(host, port, shost, sport) 84 | 85 | def forward_listen(self, host, port, bound_port, queue_maxsize): 86 | """ 87 | Forwards a TCP connection through the session. 88 | 89 | @param host: remote host 90 | @type host: str 91 | @param port: remote port 92 | @type port: int 93 | @param bound_port: populated with the actual port on the remote host 94 | @type bound_port: int 95 | @param queue_maxsize: maxium number of pending connections 96 | @type int 97 | 98 | @return: new L{Listener} instance on success or None on failure 99 | @rtype: L{Listener} 100 | """ 101 | return self._session.forward_listen( 102 | host, port, bound_port, queue_maxsize 103 | ) 104 | 105 | def hostkey_hash(self, hashtype): 106 | """ 107 | Returns the computed digest of the remote host's key. 108 | 109 | @param hashtype: values possible are 1 (HASH_MD5) or 2 (HASH_SHA1) 110 | @type hashtype: int 111 | 112 | @return: string representation of the computed hash value 113 | @rtype: str 114 | """ 115 | return self._session.hostkey_hash(hashtype) 116 | 117 | def last_error(self): 118 | """ 119 | Returns the last error in tuple format (code, message). 120 | 121 | @return: error tuple (int, str) 122 | @rtype: tuple 123 | """ 124 | return self._session.last_error() 125 | 126 | def open_session(self): 127 | """ 128 | Allocates a new L{Channel} for the session. 129 | 130 | @return: new channel opened 131 | @rtype: L{Channel} 132 | """ 133 | ret = self._session.open_session() 134 | return Channel(ret) if ret else None 135 | 136 | def set_trace(self, bitmask): 137 | """ 138 | Sets trace level on the session. 139 | 140 | @param bitmask: bitmask on libssh2.LIBSSH2_TRACE_* constant 141 | """ 142 | self._session.set_trace(bitmask) 143 | 144 | 145 | def scp_recv(self, remote_path): 146 | """ 147 | Gets a remote file via SCP Protocol. 148 | 149 | @param remote_path: absolute path of remote file to transfer 150 | @type remote_path: str 151 | 152 | @return: new channel opened 153 | @rtype: L{Channel} 154 | """ 155 | return Channel(self._session.scp_recv(remote_path)) 156 | 157 | def scp_send(self, path, mode, size): 158 | """ 159 | Sends a file to remote host via SCP protocol. 160 | 161 | @param path: absolute path of file to transfer 162 | @type path: str 163 | @param mode: file access mode to create file 164 | @type mode: int 165 | @param size: size of file being transmitted 166 | @type size: int 167 | 168 | @return: new channel opened 169 | @rtype: L{Channel} 170 | """ 171 | return Channel(self._session.scp_send(path, mode, size)) 172 | 173 | def session_method_pref(self, method_type, pref): 174 | """ 175 | Sets preferred methods to be negociated. Theses preferences must be 176 | prior to calling L{startup}. 177 | 178 | @param method_type: the method type constants 179 | @type method_type: int 180 | @param pref: coma delimited list of preferred methods 181 | @type pref: str 182 | 183 | @return: 0 on success or negative on failure 184 | @rtype: int 185 | """ 186 | self._session.session_methods(method_type, pref) 187 | 188 | def session_methods(self): 189 | """ 190 | Returns dictionary with the current actives algorithms. 191 | CS keys is Client to Server and SC keys is Server to Client. 192 | 193 | @return: dictionary with actual method negotiated 194 | @rtype: dict 195 | """ 196 | return self._session.session_methods() 197 | 198 | def set_banner(self, banner=_libssh2.DEFAULT_BANNER): 199 | """ 200 | Sets the banner that will be sent to remote host. This is optional, the 201 | banner L{_libssh2.DEFAULT_BANNER} will be sent by default. 202 | 203 | @param banner: an user defined banner 204 | @type banner: str 205 | 206 | @return: 0 on success or negative on failure 207 | @rtype: int 208 | """ 209 | return self._session.set_banner(banner) 210 | 211 | def sftp_init(self): 212 | """ 213 | Open an Sftp Channel. 214 | 215 | @return: new Sftp channel opened 216 | @rtype: L{Sftp} 217 | """ 218 | raise NotImplementedError() 219 | 220 | def setblocking(self, mode=1): 221 | """ 222 | Sets blocking mode on the session. Default mode is blocking. 223 | 224 | @param mode: blocking (1) or non blocking (0) mode 225 | 226 | @return: None 227 | """ 228 | return self._session.setblocking(mode) 229 | 230 | def getblocking(self): 231 | """ 232 | Gets blocking mode on the session. 233 | 234 | @return : blocking (1) or non blocking (0) mode 235 | @type: int 236 | """ 237 | return self._session.getblocking() 238 | 239 | def blockdirections(self): 240 | """ 241 | Gets blocking mode on the session. 242 | 243 | @return : block directions 244 | @type: int 245 | @values: LIBSSH2_SESSION_BLOCK_INBOUND: Inbound direction blocked. 246 | LIBSSH2_SESSION_BLOCK_OUTBOUND: Outbound direction blocked. 247 | """ 248 | return self._session.blockdirections() 249 | 250 | def startup(self, sock): 251 | """ 252 | Starts up the session form a socket created by a socket.socket() call. 253 | 254 | @param sock: a connected socket object 255 | @type sock: socket._socketobject 256 | 257 | @return: 0 on success or negative on failure 258 | @rtype: int 259 | """ 260 | return self._session.startup(sock) 261 | 262 | def userauth_authenticated(self): 263 | """ 264 | Returns authentication status for the given session. 265 | 266 | @return: non-zero if authenticated or 0 if not 267 | @rtype: int 268 | """ 269 | return self._session.userauth_authenticated() 270 | 271 | def userauth_list(self, username): 272 | """ 273 | Lists the authentication methods supported by a server. 274 | 275 | @param username: username which will be used while authenticating 276 | @type username: str 277 | 278 | @return: string containing a comma-separated list of authentication 279 | methods 280 | @rtype: str 281 | """ 282 | return self._session.userauth_list(username) 283 | 284 | def userauth_password(self, username, password): 285 | """ 286 | Authenticates a session with the given username and password. 287 | 288 | @param username: user to authenticate 289 | @type username: str 290 | @param password: password to use for the authentication 291 | @type password: str 292 | 293 | @return: 0 on success or negative on failure 294 | @rtype: int 295 | """ 296 | return self._session.userauth_password(username, password) 297 | 298 | def userauth_publickey_fromfile( 299 | self, username, publickey, privatekey, passphrase 300 | ): 301 | """ 302 | Authenticates a session as username using a key pair found in the 303 | pulickey and privatekey files, and passphrase if provided. 304 | 305 | @param username: user to authenticate 306 | @type username: str 307 | @param publickey: path and name of public key file 308 | @type publickey: str 309 | @param privatekey: path and name of private key file 310 | @type privatekey: str 311 | @param passphrase: passphrase to use when decoding private file 312 | @type passphrase: str 313 | 314 | @return: 0 on success or negative on failure 315 | @rtype: int 316 | """ 317 | return self._session.userauth_publickey_fromfile(username, publickey, 318 | privatekey, passphrase) 319 | 320 | def userauth_keyboardinteractive(self, username, password): 321 | """ 322 | Authenticates a session with the given username using a 323 | challenge-response authentication. 324 | 325 | @param username: user to authenticate 326 | @type username: str 327 | @param password: password using to fake keyboard method 328 | @type: str 329 | 330 | @return: 0 on success or negative on failure 331 | @rtype: int 332 | """ 333 | return self._session.userauth_keyboardinteractive(username, password, 334 | len(password)) 335 | 336 | def userauth_agent(self, username): 337 | """ 338 | Authenticates a session with a ssh-agent. 339 | 340 | @param username: user to authenticate 341 | @type username: str 342 | 343 | @return: 0 on success or negative on failure 344 | @rtype: int 345 | """ 346 | return self._session.userauth_agent(username) 347 | -------------------------------------------------------------------------------- /libssh2/sftp.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | """ 21 | Abstraction for libssh2 L{Sftp} object 22 | """ 23 | 24 | class SftpException(Exception): 25 | """ 26 | Exception raised when L{Sftp} actions fails. 27 | """ 28 | pass 29 | 30 | class Sftp(object): 31 | """ 32 | Sftp object 33 | """ 34 | def __init__(self): 35 | """ 36 | Create a new Sftp object. 37 | """ 38 | pass 39 | 40 | def close(self): 41 | """ 42 | """ 43 | raise NotImplementedError() 44 | 45 | def opendir(self): 46 | """ 47 | """ 48 | raise NotImplementedError() 49 | 50 | def readdir(self): 51 | """ 52 | """ 53 | raise NotImplementedError() 54 | 55 | def listdir(self): 56 | """ 57 | """ 58 | raise NotImplementedError() 59 | 60 | def open(self): 61 | """ 62 | """ 63 | raise NotImplementedError() 64 | 65 | 66 | def shutdown(self): 67 | """ 68 | """ 69 | raise NotImplementedError() 70 | 71 | def read(self): 72 | """ 73 | """ 74 | raise NotImplementedError() 75 | 76 | def write(self): 77 | """ 78 | """ 79 | raise NotImplementedError() 80 | 81 | def tell(self): 82 | """ 83 | """ 84 | raise NotImplementedError() 85 | 86 | def seek(self): 87 | """ 88 | """ 89 | raise NotImplementedError() 90 | 91 | def unlink(self): 92 | """ 93 | """ 94 | raise NotImplementedError() 95 | 96 | def rename(self): 97 | """ 98 | """ 99 | raise NotImplementedError() 100 | 101 | def mkdir(self): 102 | """ 103 | """ 104 | raise NotImplementedError() 105 | 106 | def rmdir(self): 107 | """ 108 | """ 109 | raise NotImplementedError() 110 | 111 | def realpath(self): 112 | """ 113 | """ 114 | raise NotImplementedError() 115 | 116 | def symlink(self): 117 | """ 118 | """ 119 | raise NotImplementedError() 120 | 121 | def getstat(self): 122 | """ 123 | """ 124 | raise NotImplementedError() 125 | 126 | def setstat(self): 127 | """ 128 | """ 129 | raise NotImplementedError() 130 | -------------------------------------------------------------------------------- /libssh2/version.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | __doc__ = """Python binding for libssh2 library""" 21 | 22 | __version_info__ = (1, 0, 3) 23 | __version__ = '.'.join([ str(v) for v in __version_info__]) 24 | __url__ = 'http://github.com/wallix/pylibssh2' 25 | __author__ = 'Sofian Brabez' 26 | __authoremail__ = 'sbz@wallix.com' 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # pylibssh2 - python bindings for libssh2 library 3 | # 4 | # Copyright (C) 2010 Wallix Inc. 5 | # 6 | # This library is free software; you can redistribute it and/or modify it 7 | # under the terms of the GNU Lesser General Public License as published by the 8 | # Free Software Foundation; either version 2.1 of the License, or (at your 9 | # option) any later version. 10 | # 11 | # This library is distributed in the hope that it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14 | # details. 15 | # 16 | # You should have received a copy of the GNU Lesser General Public License 17 | # along with this library; if not, write to the Free Software Foundation, Inc., 18 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | # 20 | """ 21 | Installation script for the libssh2 module 22 | """ 23 | from distutils.core import setup 24 | from distutils.core import Command 25 | from distutils.core import Extension 26 | from distutils.util import get_platform 27 | from platform import python_version 28 | 29 | import os, sys, glob 30 | 31 | sys.path.append('tests') 32 | sys.path.append("build/lib.%s-%s" % (get_platform(), python_version()[:3])) 33 | sys.path.append('libssh2') 34 | 35 | import version as info 36 | 37 | version = info.__version__ 38 | url = info.__url__ 39 | author = info.__author__ 40 | author_email = info.__authoremail__ 41 | 42 | long_description = '''Python binding for libssh2 library''' 43 | 44 | classifiers = """Development Status :: 4 - Beta 45 | License :: OSI Approved :: BSD License 46 | Operating System :: POSIX 47 | Programming Language :: C 48 | Programming Language :: Python 49 | Topic :: Security 50 | Topic :: Software Development :: Libraries""".split('\n') 51 | 52 | libssh2_src = glob.glob('src/*.c') 53 | libssh2_dep = glob.glob('src/*.h') 54 | libssh2_incdir = None 55 | libssh2_libdir = None 56 | 57 | if 'bsd' in sys.platform[:-1] or 'bsd' in os.uname()[0].lower(): 58 | libssh2_incdir = ['/usr/local/include/'] 59 | libssh2_libdir = ['/usr/local/lib/'] 60 | if 'darwin' in sys.platform: 61 | libssh2_incdir = ['/opt/local/include/'] 62 | libssh2_libdir = ['/opt/local/lib/'] 63 | 64 | libssh2_lib = ['ssh2'] 65 | libssh2_compile_args = ['-ggdb'] 66 | 67 | class Libssh2TestCommand(Command): 68 | user_options = [] 69 | 70 | def initialize_options(self): 71 | pass 72 | def finalize_options(self): 73 | pass 74 | 75 | def run(self): 76 | import unittest 77 | from test_session import SessionTest 78 | 79 | suite = unittest.TestSuite() 80 | suite.addTest(unittest.makeSuite(SessionTest)) 81 | 82 | runner = unittest.TextTestRunner() 83 | runner.run(suite) 84 | 85 | 86 | module = Extension('_libssh2', 87 | define_macros = [ 88 | ('MAJOR_VERSION', version[0]), 89 | ('MINOR_VERSION', version[2]), 90 | ('PATCH_VERSION', version[4]) 91 | ], 92 | sources = libssh2_src, 93 | depends = libssh2_dep, 94 | include_dirs = libssh2_incdir, 95 | library_dirs = libssh2_libdir, 96 | libraries = libssh2_lib, 97 | extra_compile_args = libssh2_compile_args) 98 | 99 | setup(name='pylibssh2', 100 | version=version, 101 | packages = ['libssh2'], 102 | package_dir = { 103 | 'libssh2' : 'libssh2' 104 | }, 105 | description = long_description, 106 | author=author, 107 | author_email=author_email, 108 | url=url, 109 | download_url='%s/download/pylibssh2-%s.tar.gz' % (url, version), 110 | ext_modules = [module], 111 | license = 'LGPL', 112 | platforms = ['Linux', 'BSD'], 113 | long_description = long_description, 114 | classifiers=classifiers, 115 | cmdclass= {'test' : Libssh2TestCommand}) 116 | -------------------------------------------------------------------------------- /src/channel.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | 26 | /* {{{ PYLIBSSH2_Channel_close 27 | */ 28 | static char PYLIBSSH2_Channel_close_doc[] = "\n\ 29 | close() -> int\n\ 30 | \n\ 31 | Closes the active channel.\n\ 32 | \n\ 33 | @param channel\n\ 34 | @type libssh2.Channel\n\ 35 | \n\ 36 | @return 0 on success or LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode)\n\ 37 | @rtype int"; 38 | 39 | static PyObject * 40 | PYLIBSSH2_Channel_close(PYLIBSSH2_CHANNEL *self, PyObject *args) 41 | { 42 | int rc; 43 | 44 | Py_BEGIN_ALLOW_THREADS 45 | rc = libssh2_channel_close(self->channel); 46 | if (rc != LIBSSH2_ERROR_EAGAIN) 47 | rc = libssh2_channel_wait_closed(self->channel); 48 | Py_END_ALLOW_THREADS 49 | 50 | if (rc && rc != LIBSSH2_ERROR_EAGAIN) { 51 | /* CLEAN: PYLIBSSH2_CHANNEL_CANT_CLOSE_MSG */ 52 | PyErr_Format(PYLIBSSH2_Error, "Unable to close the channel (error %d).", rc); 53 | return NULL; 54 | } 55 | 56 | return Py_BuildValue("i", rc); 57 | } 58 | /* }}} */ 59 | 60 | /* {{{ PYLIBSSH2_Channel_pty 61 | */ 62 | static char PYLIBSSH2_Channel_pty_doc[] = "\n\ 63 | pty(term) -> int\n\ 64 | \n\ 65 | Requests a pty with term type on a channel.\n\ 66 | \n\ 67 | @param term: terminal emulation type (vt100, ansi, etc...)\n\ 68 | @type term: str\n\ 69 | \n\ 70 | @return 0 on succes or negative on failure or if it would block\n\ 71 | @return 0 on success or LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode)\n\ 72 | @rtype int"; 73 | 74 | /* 75 | * refer libssh2_channel_request_pty_ex() 76 | */ 77 | static PyObject * 78 | PYLIBSSH2_Channel_pty(PYLIBSSH2_CHANNEL *self, PyObject *args) 79 | { 80 | int rc; 81 | /* terminal type */ 82 | char *term; 83 | /* terminal type length */ 84 | int term_len; 85 | /* terminal modes capabilities */ 86 | char *modes = NULL; 87 | /* modes length */ 88 | int modes_len = 0; 89 | /* terminal dimensions in characters */ 90 | int width = 80, height = 24; 91 | /* default dimensions */ 92 | int width_px = 0, height_px = 0; 93 | 94 | if (!PyArg_ParseTuple(args, "s#|s#iiii:pty", &term, &term_len, &modes, 95 | &modes_len, &width, &height, &width_px, &height_px)) { 96 | return NULL; 97 | } 98 | 99 | Py_BEGIN_ALLOW_THREADS 100 | rc = libssh2_channel_request_pty_ex(self->channel, term, term_len, modes, modes_len, 101 | width, height, width_px, height_px); 102 | Py_END_ALLOW_THREADS 103 | 104 | if (rc && rc != LIBSSH2_ERROR_EAGAIN) { 105 | /* CLEAN: PYLIBSSH2_CHANNEL_PTY_FAILED_MSG */ 106 | PyErr_Format(PYLIBSSH2_Error, "Failed to request pty (error %d).", rc); 107 | return NULL; 108 | } 109 | 110 | return Py_BuildValue("i", rc); 111 | } 112 | /* }}} */ 113 | 114 | /* {{{ PYLIBSSH2_Channel_pty_resize 115 | */ 116 | static char PYLIBSSH2_Channel_pty_resize_doc[] = "\n\ 117 | pty_resize(width, height, width_px, height_px) -> int\n\ 118 | \n\ 119 | Requests a pty resize on a channel with the given width and height.\n\ 120 | \n\ 121 | @param width: terminal width\n\ 122 | @type width: int\n\ 123 | @param height: terminal height\n\ 124 | @type height: int\n\ 125 | @param width_px: terminal width in pixel (opt)\n\ 126 | @type height: int\n\ 127 | @param height_px: terminal height in pixel (opt)\n\ 128 | @type height: int\n\ 129 | \n\ 130 | @return 0 on success or LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode)\n\ 131 | @rtype int"; 132 | 133 | /* 134 | * refer libssh2_channel_request_pty_size_ex() 135 | */ 136 | static PyObject * 137 | PYLIBSSH2_Channel_pty_resize(PYLIBSSH2_CHANNEL *self, PyObject *args) 138 | { 139 | int rc = -1; 140 | 141 | /* terminal dimensions in characters */ 142 | int width = 80; 143 | int height = 24; 144 | 145 | /* terminal dimensions in pixels */ 146 | int width_px = 0; 147 | int height_px = 0; 148 | 149 | if (!PyArg_ParseTuple(args,"ii|ii:pty_resize", &width, &height, 150 | &width_px, &height_px)){ 151 | return NULL; 152 | } 153 | 154 | Py_BEGIN_ALLOW_THREADS 155 | rc = libssh2_channel_request_pty_size_ex(self->channel, width, height, 156 | width_px, height_px); 157 | Py_END_ALLOW_THREADS 158 | 159 | if (rc && rc != LIBSSH2_ERROR_EAGAIN) { 160 | PyErr_Format(PYLIBSSH2_Error, "Failed to resize pty (error %d).", rc); 161 | return NULL; 162 | } 163 | 164 | return Py_BuildValue("i",rc); 165 | } 166 | /* }}} */ 167 | 168 | /* {{{ PYLIBSSH2_Channel_shell 169 | */ 170 | static char PYLIBSSH2_Channel_shell_doc[] = "\n\ 171 | shell() -> int\n\ 172 | \n\ 173 | Requests a shell on the channel.\n\ 174 | \n\ 175 | @return 0 on success or LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode)\n\ 176 | @rtype int"; 177 | 178 | static PyObject * 179 | PYLIBSSH2_Channel_shell(PYLIBSSH2_CHANNEL *self, PyObject *args) 180 | { 181 | int rc; 182 | 183 | Py_BEGIN_ALLOW_THREADS 184 | rc = libssh2_channel_shell(self->channel); 185 | Py_END_ALLOW_THREADS 186 | 187 | if (rc && rc != LIBSSH2_ERROR_EAGAIN) { 188 | /* CLEAN: PYLIBSSH2_CHANNEL_CANT_REQUEST_SHELL_MSG */ 189 | PyErr_Format(PYLIBSSH2_Error, "Unable to request shell on allocated pty (error %d).", rc); 190 | return NULL; 191 | } 192 | 193 | return Py_BuildValue("i", rc); 194 | } 195 | /* }}} */ 196 | 197 | /* {{{ PYLIBSSH2_Channel_execute 198 | */ 199 | static char PYLIBSSH2_Channel_execute_doc[] = "\n\ 200 | execute(command) -> int\n\ 201 | \n\ 202 | Executes command on the channel.\n\ 203 | \n\ 204 | @param command: message data\n\ 205 | @type command: str\n\ 206 | \n\ 207 | @return 0 on success or LIBSSH2_ERROR_EAGAIN if it would block (non blocking mode)\n\ 208 | @rtype int"; 209 | 210 | static PyObject * 211 | PYLIBSSH2_Channel_execute(PYLIBSSH2_CHANNEL *self, PyObject *args) 212 | { 213 | int rc; 214 | /* command to execute */ 215 | char *command; 216 | 217 | if (!PyArg_ParseTuple(args, "s:execute", &command)) 218 | return NULL; 219 | 220 | Py_BEGIN_ALLOW_THREADS 221 | rc = libssh2_channel_exec(self->channel, command); 222 | Py_END_ALLOW_THREADS 223 | 224 | if (rc && rc != LIBSSH2_ERROR_EAGAIN) { 225 | /* CLEAN: PYLIBSSH2_CANT_REQUEST_EXEC_COMMAND_MSG */ 226 | PyErr_Format(PYLIBSSH2_Error, "Unable to request exec command (error %d).", rc); 227 | return NULL; 228 | } 229 | 230 | return Py_BuildValue("i", rc); 231 | } 232 | /* }}} */ 233 | 234 | /* {{{ PYLIBSSH2_Channel_setenv 235 | */ 236 | static char PYLIBSSH2_Channel_setenv_doc[] = "\n\ 237 | setenv(name, value) -> int\n\ 238 | \n\ 239 | Sets envrionment variable on the channel.\n\ 240 | \n\ 241 | @param name: evironment variable name\n\ 242 | @type name: str\n\ 243 | @param value: evironment variable value\n\ 244 | @type value: str\n\ 245 | \n\ 246 | @return 0 on success or negative on failure (LIBSSH2_ERROR_EAGAIN if it would block)\n\ 247 | @rtype int"; 248 | 249 | static PyObject * 250 | PYLIBSSH2_Channel_setenv(PYLIBSSH2_CHANNEL *self, PyObject *args) 251 | { 252 | int rc; 253 | /* variable envrionnement name */ 254 | char *env_key; 255 | /* variable envrionnement value */ 256 | char *env_val; 257 | 258 | if (!PyArg_ParseTuple(args, "ss:setenv", &env_key, &env_val)) 259 | return NULL; 260 | 261 | Py_BEGIN_ALLOW_THREADS 262 | rc = libssh2_channel_setenv(self->channel, env_key, env_val); 263 | Py_END_ALLOW_THREADS 264 | 265 | if (rc == -1) { 266 | /* CLEAN: PYLIBSSH2_CANT_SET_ENVRIONNEMENT_VARIABLE_MSG */ 267 | PyErr_SetString(PYLIBSSH2_Error,"Unable to set envrionnement variable."); 268 | return NULL; 269 | } 270 | 271 | return Py_BuildValue("i", rc); 272 | } 273 | /* }}} */ 274 | 275 | /* {{{ PYLIBSSH2_Channel_setblocking 276 | */ 277 | static char PYLIBSSH2_Channel_setblocking_doc[] = "\n\ 278 | setblocking([mode])\n\ 279 | \n\ 280 | Sets blocking mode on the channel. Default mode is blocking.\n\ 281 | \n\ 282 | @param mode: blocking (1) or non blocking (0) mode\n\ 283 | @type mode: int"; 284 | 285 | static PyObject * 286 | PYLIBSSH2_Channel_setblocking(PYLIBSSH2_CHANNEL *self, PyObject *args) 287 | { 288 | /* 1 blocking, 0 non blocking */ 289 | int block = 1; 290 | 291 | if (!PyArg_ParseTuple(args, "i:setblocking", &block)) 292 | return NULL; 293 | 294 | libssh2_channel_set_blocking(self->channel, block); 295 | 296 | Py_INCREF(Py_None); 297 | return Py_None; 298 | } 299 | /* }}} */ 300 | 301 | /* {{{ PYLIBSSH2_Channel_read 302 | */ 303 | static char PYLIBSSH2_Channel_read_doc[] = "\n\ 304 | read(size) -> str\n\ 305 | \n\ 306 | Reads size bytes on the channel.\n\ 307 | \n\ 308 | @param size: size of the buffer storage\n\ 309 | @type size: int\n\ 310 | \n\ 311 | @return string containing bytes read or negative value on failure\n\ 312 | LIBSSH2_ERROR_EAGAIN if it would block\n\ 313 | None if EOF is encoutered\n\ 314 | @rtype str or int or none"; 315 | 316 | static PyObject * 317 | PYLIBSSH2_Channel_read(PYLIBSSH2_CHANNEL *self, PyObject *args) 318 | { 319 | int rc; 320 | int buffer_size; 321 | /* buffer to read as a python object */ 322 | PyObject *buffer; 323 | 324 | if (!PyArg_ParseTuple(args, "i|i:read", &buffer_size)) 325 | return NULL; 326 | 327 | buffer = PyString_FromStringAndSize(NULL, buffer_size); 328 | if (buffer == NULL) { 329 | return NULL; 330 | } 331 | 332 | if (libssh2_channel_eof(self->channel) != 1) { 333 | Py_BEGIN_ALLOW_THREADS 334 | rc = libssh2_channel_read(self->channel, PyString_AsString(buffer), 335 | buffer_size); 336 | Py_END_ALLOW_THREADS 337 | 338 | if (rc > 0) { 339 | if (rc != buffer_size && _PyString_Resize(&buffer, rc) < 0) 340 | return NULL; 341 | return buffer; 342 | } 343 | else if (rc == LIBSSH2_ERROR_EAGAIN) { 344 | Py_XDECREF(buffer); 345 | return Py_BuildValue("i", rc); 346 | } 347 | } 348 | 349 | Py_XDECREF(buffer); 350 | Py_INCREF(Py_None); 351 | 352 | return Py_None; 353 | } 354 | /* }}} */ 355 | 356 | /* {{{ PYLIBSSH2_Channel_read_stderr 357 | */ 358 | static char PYLIBSSH2_Channel_read_stderr_doc[] = "\n\ 359 | read_stderr(size) -> str\n\ 360 | \n\ 361 | Reads size bytes on the channel stderr.\n\ 362 | \n\ 363 | @param size: size of the buffer storage\n\ 364 | @type size: int\n\ 365 | \n\ 366 | @return string containing bytes read or negative value on failure\n\ 367 | LIBSSH2_ERROR_EAGAIN if it would block\n\ 368 | None if EOF is encoutered\n\ 369 | @rtype str or int or none"; 370 | 371 | static PyObject * 372 | PYLIBSSH2_Channel_read_stderr(PYLIBSSH2_CHANNEL *self, PyObject *args) 373 | { 374 | int rc; 375 | int buffer_size; 376 | /* buffer to read as a python object */ 377 | PyObject *buffer; 378 | 379 | if (!PyArg_ParseTuple(args, "i|i:read_stderr", &buffer_size)) 380 | return NULL; 381 | 382 | buffer = PyString_FromStringAndSize(NULL, buffer_size); 383 | if (buffer == NULL) { 384 | return NULL; 385 | } 386 | 387 | if (libssh2_channel_eof(self->channel) != 1) { 388 | Py_BEGIN_ALLOW_THREADS 389 | rc = libssh2_channel_read_stderr(self->channel, PyString_AsString(buffer), 390 | buffer_size); 391 | Py_END_ALLOW_THREADS 392 | 393 | if (rc > 0) { 394 | if (rc != buffer_size && _PyString_Resize(&buffer, rc) < 0) 395 | return NULL; 396 | return buffer; 397 | } 398 | else if (rc == LIBSSH2_ERROR_EAGAIN) { 399 | Py_XDECREF(buffer); 400 | return Py_BuildValue("i", rc); 401 | } 402 | } 403 | 404 | Py_XDECREF(buffer); 405 | Py_INCREF(Py_None); 406 | 407 | return Py_None; 408 | } 409 | /* }}} */ 410 | 411 | /* {{{ PYLIBSSH2_Channel_read_ex 412 | */ 413 | static char PYLIBSSH2_Channel_read_ex_doc[] = "\n\ 414 | read(size, [stream_id]) -> str\n\ 415 | \n\ 416 | Reads size bytes on the channel.\n\ 417 | \n\ 418 | @param size: size of the buffer storage\n\ 419 | @type size: int\n\ 420 | @param stream_id: substream ID number\n\ 421 | @type stream_id: int\n\ 422 | \n\ 423 | @return string containing bytes read or negative value on failure\n\ 424 | @rtype str or int"; 425 | 426 | static PyObject * 427 | PYLIBSSH2_Channel_read_ex(PYLIBSSH2_CHANNEL *self, PyObject *args) 428 | { 429 | int rc; 430 | int buffer_size; 431 | int stream_id = 0; 432 | /* buffer to read as a python object */ 433 | PyObject *buffer; 434 | char * cbuf; 435 | 436 | if (!PyArg_ParseTuple(args, "i|i:read_ex", &buffer_size, &stream_id)) 437 | return NULL; 438 | buffer = PyString_FromStringAndSize(NULL, buffer_size); 439 | if (buffer == NULL) { 440 | return NULL; 441 | } 442 | cbuf = PyString_AsString(buffer); 443 | 444 | Py_BEGIN_ALLOW_THREADS 445 | rc = libssh2_channel_read_ex(self->channel, stream_id, cbuf, buffer_size); 446 | Py_END_ALLOW_THREADS 447 | 448 | if (rc > 0) { 449 | if (rc != buffer_size && _PyString_Resize(&buffer, rc) < 0) 450 | return NULL; 451 | } 452 | /** 453 | we do NOT increment the reference on the buffer anymore 454 | it is already done by PyString_FromStringAndSize 455 | */ 456 | return Py_BuildValue("iN", rc, buffer); 457 | } 458 | /* }}} */ 459 | 460 | /* {{{ PYLIBSSH2_Channel_write 461 | */ 462 | static char PYLIBSSH2_Channel_write_doc[] = "\n\ 463 | write(message) -> int\n\ 464 | \n\ 465 | Writes data on a channel.\n\ 466 | \n\ 467 | @param message: data to write\n\ 468 | @type message: str\n\ 469 | \n\ 470 | @return 0 on success or failure\n\ 471 | @rtype int"; 472 | 473 | static PyObject * 474 | PYLIBSSH2_Channel_write(PYLIBSSH2_CHANNEL *self, PyObject *args) 475 | { 476 | int rc; 477 | char *message; 478 | int message_len; 479 | 480 | if (!PyArg_ParseTuple(args, "s#:write", &message, &message_len)) 481 | return NULL; 482 | 483 | Py_BEGIN_ALLOW_THREADS 484 | rc = libssh2_channel_write(self->channel, message, message_len); 485 | Py_END_ALLOW_THREADS 486 | 487 | if (rc == -1) { 488 | /* CLEAN: PYLIBSSH2_CANT_WRITE_CHANNEL_MSG */ 489 | PyErr_SetString(PYLIBSSH2_Error,"Unable to write channel."); 490 | return NULL; 491 | } 492 | 493 | return Py_BuildValue("i", rc); 494 | } 495 | /* }}} */ 496 | 497 | /* {{{ PYLIBSSH2_Channel_flush 498 | */ 499 | static char PYLIBSSH2_Channel_flush_doc[] = "\n\ 500 | flush() -> int\n\ 501 | \n\ 502 | Flushs the read buffer for a given channel.\n\ 503 | \n\ 504 | @return 0 on success or negative on failure\n\ 505 | @rtype int"; 506 | 507 | static PyObject * 508 | PYLIBSSH2_Channel_flush(PYLIBSSH2_CHANNEL *self, PyObject *args) 509 | { 510 | int rc; 511 | 512 | Py_BEGIN_ALLOW_THREADS 513 | rc = libssh2_channel_flush(self->channel); 514 | Py_END_ALLOW_THREADS 515 | 516 | if (rc == -1) { 517 | /* CLEAN: PYLIBSSH2_CANT_FLUSH_CHANNEL_MSG */ 518 | PyErr_SetString(PYLIBSSH2_Error, "Unable to flush channel."); 519 | return NULL; 520 | } 521 | 522 | return Py_BuildValue("i", rc); 523 | } 524 | /* }}} */ 525 | 526 | /* {{{ PYLIBSSH2_Channel_exit_status 527 | */ 528 | static char PYLIBSSH2_Channel_exit_status_doc[] = "\n\ 529 | exit_status() -> int \n\ 530 | \n\ 531 | Gets the exit code raised by the process running on the remote host.\n\ 532 | \n\ 533 | @return the exit status reported by remote host or 0 on failure\n\ 534 | @rtype int"; 535 | 536 | static PyObject * 537 | PYLIBSSH2_Channel_exit_status(PYLIBSSH2_CHANNEL *self, PyObject *args) 538 | { 539 | return Py_BuildValue("i", libssh2_channel_get_exit_status(self->channel)); 540 | } 541 | /* }}} */ 542 | 543 | /* {{{ PYLIBSSH2_Channel_eof 544 | */ 545 | static char PYLIBSSH2_Channel_eof_doc[] = "\n\ 546 | eof() -> int\n\ 547 | \n\ 548 | Checks if the remote host has sent an EOF status.\n\ 549 | \n\ 550 | @return 1 if the remote host has sent EOF otherwise 0\n\ 551 | @rtype int"; 552 | 553 | static PyObject * 554 | PYLIBSSH2_Channel_eof(PYLIBSSH2_CHANNEL *self, PyObject *args) 555 | { 556 | return Py_BuildValue("i", libssh2_channel_eof(self->channel)); 557 | } 558 | /* }}} */ 559 | 560 | /* {{{ PYLIBSSH2_Channel_send_eof 561 | */ 562 | static char PYLIBSSH2_Channel_send_eof_doc[] = "\n\ 563 | send_eof() -> int\n\ 564 | \n\ 565 | Sends EOF status on the channel to remote server.\n\ 566 | \n\ 567 | @return 0 on success or negative on failure\n\ 568 | @rtype int"; 569 | 570 | static PyObject * 571 | PYLIBSSH2_Channel_send_eof(PYLIBSSH2_CHANNEL *self, PyObject *args) 572 | { 573 | int rc; 574 | 575 | Py_BEGIN_ALLOW_THREADS 576 | rc = libssh2_channel_send_eof(self->channel); 577 | Py_END_ALLOW_THREADS 578 | 579 | if (rc == -1) { 580 | /* CLEAN: PYLIBSSH2_CANT_SEND_EOF_MSG */ 581 | PyErr_SetString(PYLIBSSH2_Error, "Unable to send a EOF on channel."); 582 | return NULL; 583 | } 584 | 585 | return Py_BuildValue("i", rc); 586 | } 587 | /* }}} */ 588 | 589 | /* {{{ PYLIBSSH2_Channel_wait_closed 590 | */ 591 | static char PYLIBSSH2_Channel_wait_closed_doc[] = "\n\ 592 | wait_closed() -> int\n\ 593 | \n\ 594 | Wait for the remote channel to ack channel close.\n\ 595 | \n\ 596 | @param channel\n\ 597 | @type libssh2.Channel\n\ 598 | \n\ 599 | @return 0 on success or negative on failure\n\ 600 | @rtype int"; 601 | 602 | static PyObject * 603 | PYLIBSSH2_Channel_wait_closed(PYLIBSSH2_CHANNEL *self, PyObject *args) 604 | { 605 | int rc; 606 | 607 | Py_BEGIN_ALLOW_THREADS 608 | rc = libssh2_channel_wait_closed(self->channel); 609 | Py_END_ALLOW_THREADS 610 | 611 | return Py_BuildValue("i", rc); 612 | } 613 | /* }}} */ 614 | 615 | /* {{{ PYLIBSSH2_Channel_window_read 616 | */ 617 | static char PYLIBSSH2_Channel_window_read_doc[] = "\n\ 618 | window_read(read_avail, window_size_initial) -> int\n\ 619 | \n\ 620 | Checks the status of the read window.\n\ 621 | \n\ 622 | \n\ 623 | @return windows: the number of bytes which the remote end may send without\n\ 624 | @return read_avail: number of bytes available to be read\n\ 625 | @return window_size_initial: as defined by the channel_open request\n\ 626 | @rtype (int, int, int)"; 627 | 628 | static PyObject * 629 | PYLIBSSH2_Channel_window_read(PYLIBSSH2_CHANNEL *self, PyObject *args) 630 | { 631 | unsigned long rc=0; 632 | unsigned long read_avail; 633 | unsigned long window_size_initial; 634 | 635 | Py_BEGIN_ALLOW_THREADS 636 | rc = libssh2_channel_window_read_ex(self->channel, &read_avail, &window_size_initial); 637 | Py_END_ALLOW_THREADS 638 | 639 | return Py_BuildValue("(kkk)", rc, read_avail, window_size_initial); 640 | } 641 | /* }}} */ 642 | 643 | static char PYLIBSSH2_Channel_window_write_doc[] = "\n" 644 | "window_write(write_avail) -> int\n" 645 | "\n" 646 | "check the status of the write window.\n" 647 | "\n" 648 | "\n" 649 | "@return windows: the number of bytes which may be safely writen on the\n" 650 | "channel without blocking." 651 | "@return window_size_initial: as defined by the channel_open request\n" 652 | "@rtype (int, int)"; 653 | 654 | static PyObject * 655 | PYLIBSSH2_Channel_window_write(PYLIBSSH2_CHANNEL *self) 656 | { 657 | unsigned long rc=0; 658 | unsigned long window_size_initial; 659 | 660 | Py_BEGIN_ALLOW_THREADS 661 | rc = libssh2_channel_window_write_ex(self->channel, &window_size_initial); 662 | Py_END_ALLOW_THREADS 663 | 664 | return Py_BuildValue("(kk)", rc, window_size_initial); 665 | } 666 | /* }}} */ 667 | 668 | /* {{{ PYLIBSSH2_Channel_x11_req 669 | */ 670 | static char PYLIBSSH2_Channel_x11_req_doc[] = "\n\ 671 | x11_req([single_connection, auth_proto, auth_cookie, display]) -> int\n\ 672 | \n\ 673 | Requests an X11 Forwarding on the channel.\n\ 674 | \n\ 675 | @param single_connection: forward a single connection\n\ 676 | @type single_connection: int\n\ 677 | @param auth_proto: X11 authentication protocol to use\n\ 678 | @type auth_proto: str\n\ 679 | @param auth_cookie: the cookie\n\ 680 | @type auth_cookie: str\n\ 681 | @param display: screen number\n\ 682 | @type display: int\n\ 683 | \n\ 684 | @return 0 on success or negative on failure\n\ 685 | @rtype int"; 686 | 687 | static PyObject * 688 | PYLIBSSH2_Channel_x11_req(PYLIBSSH2_CHANNEL *self, PyObject *args) 689 | { 690 | int rc; 691 | int single_connection = 0; 692 | char *auth_proto = NULL; 693 | char *auth_cookie = NULL; 694 | int display = 0; 695 | 696 | if (!PyArg_ParseTuple(args, "|issi:x11_req", &single_connection, &auth_proto, &auth_cookie, &display)) { 697 | return NULL; 698 | } 699 | 700 | Py_BEGIN_ALLOW_THREADS 701 | rc = libssh2_channel_x11_req_ex(self->channel, single_connection, auth_proto, auth_cookie, display); 702 | Py_END_ALLOW_THREADS 703 | 704 | return Py_BuildValue("i", rc); 705 | } 706 | /* }}} */ 707 | 708 | /* {{{ PYLIBSSH2_Channel_poll_read 709 | */ 710 | static char PYLIBSSH2_Channel_poll_read_doc[] = "\n\ 711 | poll_read([extended]) -> int\n\ 712 | \n\ 713 | Checks if data is available on the channel.\n\ 714 | \n\ 715 | @param extended: if message channel datas is extended\n\ 716 | @type extended: int\n\ 717 | \n\ 718 | @return 1 when data is available or 0 otherwise\n\ 719 | @rtype int"; 720 | 721 | static PyObject * 722 | PYLIBSSH2_Channel_poll_read(PYLIBSSH2_CHANNEL *self, PyObject *args) 723 | { 724 | int rc; 725 | int extended = 0; 726 | 727 | if (!PyArg_ParseTuple(args, "|i:poll_read", &extended)) { 728 | return NULL; 729 | } 730 | 731 | Py_BEGIN_ALLOW_THREADS 732 | rc = libssh2_poll_channel_read(self->channel, extended); 733 | Py_END_ALLOW_THREADS; 734 | 735 | return Py_BuildValue("i", rc); 736 | } 737 | /* }}} */ 738 | 739 | /* {{{ PYLIBSSH2_Channel_methods[] 740 | * 741 | * ADD_METHOD(name) expands to a correct PyMethodDef declaration 742 | * { 'name', (PyCFunction)PYLIBSSH2_Channel_name, METHOD_VARARGS } 743 | * for convenience 744 | */ 745 | 746 | #define ADD_METHOD(name) \ 747 | { #name, (PyCFunction)PYLIBSSH2_Channel_##name, METH_VARARGS, PYLIBSSH2_Channel_##name##_doc } 748 | static PyMethodDef PYLIBSSH2_Channel_methods[] = 749 | { 750 | ADD_METHOD(close), 751 | ADD_METHOD(pty), 752 | ADD_METHOD(pty_resize), 753 | ADD_METHOD(shell), 754 | ADD_METHOD(execute), 755 | ADD_METHOD(setenv), 756 | ADD_METHOD(setblocking), 757 | ADD_METHOD(read_ex), 758 | ADD_METHOD(read), 759 | ADD_METHOD(read_stderr), 760 | ADD_METHOD(write), 761 | ADD_METHOD(flush), 762 | ADD_METHOD(eof), 763 | ADD_METHOD(exit_status), 764 | ADD_METHOD(send_eof), 765 | ADD_METHOD(wait_closed), 766 | ADD_METHOD(window_read), 767 | ADD_METHOD(window_write), 768 | ADD_METHOD(poll_read), 769 | ADD_METHOD(x11_req), 770 | { NULL, NULL } 771 | }; 772 | #undef ADD_METHOD 773 | /* }}} */ 774 | 775 | /* {{{ PYLIBSSH2_Channel_New 776 | */ 777 | PYLIBSSH2_CHANNEL * 778 | PYLIBSSH2_Channel_New(LIBSSH2_CHANNEL *channel, int dealloc) 779 | { 780 | PYLIBSSH2_CHANNEL *self; 781 | 782 | self = PyObject_New(PYLIBSSH2_CHANNEL, &PYLIBSSH2_Channel_Type); 783 | if (self == NULL) { 784 | return NULL; 785 | } 786 | 787 | self->channel = channel; 788 | self->dealloc = dealloc; 789 | 790 | return self; 791 | } 792 | /* }}} */ 793 | 794 | /* {{{ PYLIBSSH2_Channel_dealloc 795 | */ 796 | static void 797 | PYLIBSSH2_Channel_dealloc(PYLIBSSH2_CHANNEL *self) 798 | { 799 | PyObject_Del(self); 800 | } 801 | /* }}} */ 802 | 803 | /* {{{ PYLIBSSH2_Channel_getattr 804 | */ 805 | static PyObject * 806 | PYLIBSSH2_Channel_getattr(PYLIBSSH2_CHANNEL *self, char *name) 807 | { 808 | return Py_FindMethod(PYLIBSSH2_Channel_methods, (PyObject *)self, name); 809 | } 810 | /* }}} */ 811 | 812 | /* {{{ PYLIBSSH2_Channel_Type 813 | * see /usr/include/python2.5/object.h line 261 814 | */ 815 | PyTypeObject PYLIBSSH2_Channel_Type = { 816 | PyObject_HEAD_INIT(NULL) 817 | 0, /* ob_size */ 818 | "Channel", /* tp_name */ 819 | sizeof(PYLIBSSH2_CHANNEL), /* tp_basicsize */ 820 | 0, /* tp_itemsize */ 821 | (destructor)PYLIBSSH2_Channel_dealloc, /* tp_dealloc */ 822 | 0, /* tp_print */ 823 | (getattrfunc)PYLIBSSH2_Channel_getattr, /* tp_getattr */ 824 | 0, /* tp_setattr */ 825 | 0, /* tp_compare */ 826 | 0, /* tp_repr */ 827 | 0, /* tp_as_number */ 828 | 0, /* tp_as_sequence */ 829 | 0, /* tp_as_mapping */ 830 | 0, /* tp_hash */ 831 | 0, /* tp_call */ 832 | 0, /* tp_str */ 833 | 0, /* tp_getattro */ 834 | 0, /* tp_setattro */ 835 | 0, /* tp_as_buffer */ 836 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 837 | "Channel objects", /* tp_doc */ 838 | }; 839 | /* }}} */ 840 | 841 | /* {{{ init_libssh2_Channel 842 | */ 843 | int 844 | init_libssh2_Channel(PyObject *dict) 845 | { 846 | PYLIBSSH2_Channel_Type.ob_type = &PyType_Type; 847 | Py_XINCREF(&PYLIBSSH2_Channel_Type); 848 | PyDict_SetItemString(dict, "ChannelType", (PyObject *)&PYLIBSSH2_Channel_Type); 849 | 850 | return 1; 851 | } 852 | /* }}} */ 853 | -------------------------------------------------------------------------------- /src/channel.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_CHANNEL_H_ 22 | #define _PYLIBSSH2_CHANNEL_H_ 23 | 24 | #include 25 | #include 26 | 27 | extern int init_libssh2_Channel(PyObject *); 28 | 29 | extern PyTypeObject PYLIBSSH2_Channel_Type; 30 | 31 | #define PYLIBSSH2_Channel_Check(v) ((v)->ob_type == &PYLIBSSH2_Channel_Type) 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | LIBSSH2_CHANNEL *channel; 36 | int dealloc; 37 | } PYLIBSSH2_CHANNEL; 38 | 39 | #endif /* _PYLIBSSH2_CHANNEL_H_ */ 40 | -------------------------------------------------------------------------------- /src/listener.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | /* {{{ PYLIBSSH2_Listener_accept 26 | */ 27 | static char PYLIBSSH2_Listener_accept_doc[] = "\n\ 28 | \n\ 29 | Arguments:\n\ 30 | \n\ 31 | Returns:\n\ 32 | "; 33 | 34 | static PyObject * 35 | PYLIBSSH2_Listener_accept(PYLIBSSH2_LISTENER *self, PyObject *args) 36 | { 37 | LIBSSH2_CHANNEL *channel; 38 | 39 | Py_BEGIN_ALLOW_THREADS 40 | channel = libssh2_channel_forward_accept(self->listener); 41 | Py_END_ALLOW_THREADS 42 | 43 | if (channel == NULL) { 44 | PyErr_SetString(PYLIBSSH2_Error, "Unable to accept listener on channel."); 45 | Py_INCREF(Py_None); 46 | return Py_None; 47 | } 48 | 49 | return (PyObject *)PYLIBSSH2_Channel_New(channel, 1); 50 | } 51 | /* }}} */ 52 | 53 | /* {{{ PYLIBSSH2_Listener_cancel 54 | */ 55 | static char PYLIBSSH2_Listener_cancel_doc[] = "\n\ 56 | \n\ 57 | Arguments:\n\ 58 | \n\ 59 | Returns:\n\ 60 | "; 61 | 62 | static PyObject * 63 | PYLIBSSH2_Listener_cancel(PYLIBSSH2_LISTENER *self, PyObject *args) 64 | { 65 | int rc; 66 | 67 | Py_BEGIN_ALLOW_THREADS 68 | rc = libssh2_channel_forward_cancel(self->listener); 69 | Py_END_ALLOW_THREADS 70 | 71 | return Py_BuildValue("i", rc); 72 | } 73 | /* }}} */ 74 | 75 | /* {{{ PYLIBSSH2_Listener_methods[] 76 | * 77 | * ADD_METHOD(name) expands to a correct PyMethodDef declaration 78 | * { 'name', (PyCFunction)PYLIBSSH2_Listener_name, METHOD_VARARGS } 79 | * for convenience 80 | */ 81 | #define ADD_METHOD(name) \ 82 | { #name, (PyCFunction)PYLIBSSH2_Listener_##name, METH_VARARGS, PYLIBSSH2_Listener_##name##_doc } 83 | 84 | struct PyMethodDef PYLIBSSH2_Listener_methods[] = { 85 | ADD_METHOD(accept), 86 | ADD_METHOD(cancel), 87 | { NULL, NULL } 88 | }; 89 | #undef ADD_METHOD 90 | /* }}} */ 91 | 92 | /* {{{ PYLIBSSH2_Listener_New 93 | */ 94 | PYLIBSSH2_LISTENER * 95 | PYLIBSSH2_Listener_New(LIBSSH2_LISTENER *listener, int dealloc) 96 | { 97 | PYLIBSSH2_LISTENER *self; 98 | 99 | self = PyObject_New(PYLIBSSH2_LISTENER, &PYLIBSSH2_Listener_Type); 100 | if (self == NULL) { 101 | return NULL; 102 | } 103 | 104 | self->listener = listener; 105 | self->dealloc = dealloc; 106 | 107 | return self; 108 | } 109 | /* }}} */ 110 | 111 | /* {{{ PYLIBSSH2_Listener_dealloc 112 | */ 113 | static void 114 | PYLIBSSH2_Listener_dealloc(PYLIBSSH2_LISTENER *self) 115 | { 116 | if (self) { 117 | PyObject_Del(self); 118 | } 119 | } 120 | /* }}} */ 121 | 122 | /* {{{ PYLIBSSH2_Listener_getattr 123 | */ 124 | static PyObject * 125 | PYLIBSSH2_Listener_getattr(PYLIBSSH2_LISTENER *self, char *name) 126 | { 127 | return Py_FindMethod(PYLIBSSH2_Listener_methods, (PyObject *) self, name); 128 | } 129 | /* }}} */ 130 | 131 | /* {{{ PYLIBSSH2_Listener_Type 132 | * 133 | * see /usr/include/python2.5/object.h line 261 134 | */ 135 | PyTypeObject PYLIBSSH2_Listener_Type = { 136 | PyObject_HEAD_INIT(NULL) 137 | 0, /* ob_size */ 138 | "Listener", /* tp_name */ 139 | sizeof(PYLIBSSH2_LISTENER), /* tp_basicsize */ 140 | 0, /* tp_itemsize */ 141 | (destructor)PYLIBSSH2_Listener_dealloc, /* tp_dealloc */ 142 | 0, /* tp_print */ 143 | (getattrfunc)PYLIBSSH2_Listener_getattr, /* tp_getattr */ 144 | 0, /* tp_setattr */ 145 | 0, /* tp_compare */ 146 | 0, /* tp_repr */ 147 | 0, /* tp_as_number */ 148 | 0, /* tp_as_sequence */ 149 | 0, /* tp_as_mapping */ 150 | 0, /* tp_hash */ 151 | 0, /* tp_call */ 152 | 0, /* tp_str */ 153 | 0, /* tp_getattro */ 154 | 0, /* tp_setattro */ 155 | 0, /* tp_as_buffer */ 156 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 157 | "Listener objects", /* tp_doc */ 158 | }; 159 | /* }}} */ 160 | 161 | /* {{{ init_libssh2_Listener 162 | */ 163 | int 164 | init_libssh2_Listener(PyObject *dict) 165 | { 166 | PYLIBSSH2_Listener_Type.ob_type = &PyType_Type; 167 | Py_XINCREF(&PYLIBSSH2_Listener_Type); 168 | PyDict_SetItemString(dict, "ListenerType", (PyObject *)&PYLIBSSH2_Listener_Type); 169 | 170 | return 1; 171 | } 172 | /* }}} */ 173 | -------------------------------------------------------------------------------- /src/listener.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_LISTENER_H_ 22 | #define _PYLIBSSH2_LISTENER_H_ 23 | 24 | #include 25 | #include 26 | 27 | extern int init_libssh2_Listener(PyObject *); 28 | 29 | extern PyTypeObject PYLIBSSH2_Listener_Type; 30 | 31 | #define PYLIBSSH2_Listener_Check(v) ((v)->ob_type == &PYLIBSSH2_Listener_Type) 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | LIBSSH2_LISTENER *listener; 36 | int dealloc; 37 | } PYLIBSSH2_LISTENER; 38 | 39 | #endif /* _PYLIBSSH2_LISTENER_H_ */ 40 | -------------------------------------------------------------------------------- /src/pylibssh2.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | /* {{{ PYLIBSSH2_doc 26 | */ 27 | PyDoc_STRVAR(PYLIBSSH2_doc, 28 | "Python binding for libssh2 library\n\ 29 | \n\ 30 | pylibssh2 is a C extension module around C library libssh2. It provide an\n\ 31 | easy way to manage SSH connections in Python.\n\ 32 | \n\ 33 | The high-level API start with creation of an L{Session} object with a\n\ 34 | socket-like object connected. Then create a L{Channel} with L{open_session}\n\ 35 | method on the session instance.\n\ 36 | \n"); 37 | 38 | /* }}} */ 39 | 40 | PyObject *PYLIBSSH2_Error; 41 | 42 | /* {{{ PYLIBSSH2_Session 43 | */ 44 | PyDoc_STRVAR(PYLIBSSH2_Session_doc, 45 | "\n\ 46 | This class provide SSH Session operations.\n\ 47 | \n\ 48 | close() -- closes the session\n\ 49 | direct_tcpip() -- tunnels a TCP connection\n\ 50 | forward_listen() -- forwards a TCP connection\n\ 51 | hostkey_hash() -- returns the computed digest of the remote host key\n\ 52 | last_error() -- returns the last error in tuple format\n\ 53 | open_session() -- allocates a new channel\n\ 54 | scp_recv() -- requests a remote file via SCP protocol\n\ 55 | scp_send() -- sends a remote file via SCP protocol\n\ 56 | session_method_pref() -- sets preferred methods to be negociated\n\ 57 | session_methods() -- returns a dictionnary with the currently active algorithms\n\ 58 | set_banner() -- sets the banner that will be sent to remote host\n\ 59 | sftp_init() -- opens an SFTP Channel\n\ 60 | startup() -- starts up the session from a socket\n\ 61 | userauth_authenticated() -- returns authentification status\n\ 62 | userauth_list() -- lists the authentification methods\n\ 63 | userauth_password() -- authenticates a session with credentials\n\ 64 | userauth_publickey() -- authenticates a session with a publickey\n\ 65 | userauth_publickey_fromfile() -- authenticates a session with publickey\n\ 66 | userauth_agent() -- authenticates a session with a ssh-agent\n\ 67 | "); 68 | 69 | static PyObject * 70 | PYLIBSSH2_Session(PyObject *self, PyObject *args) 71 | { 72 | int dealloc = 1; 73 | 74 | if (!PyArg_ParseTuple(args, "|i:Session", &dealloc)) { 75 | return NULL; 76 | } 77 | 78 | return (PyObject *)PYLIBSSH2_Session_New(libssh2_session_init(), dealloc); 79 | } 80 | /* }}} */ 81 | 82 | /* {{{ PYLIBSSH2_Channel 83 | */ 84 | PyDoc_STRVAR(PYLIBSSH2_Channel_doc, 85 | "\n\ 86 | This class provide SSH Channel operations.\n\ 87 | \n\ 88 | close() -- closes the active channel\n\ 89 | eof() -- checks if the remote host has sent an EOF status\n\ 90 | execute() -- executes command of the channel\n\ 91 | exit_status() -- gets the exit code\n\ 92 | flush() -- flushs the read buffer\n\ 93 | poll() -- polls for activity on the channel\n\ 94 | poll_read() -- checks if data is available on the channel\n\ 95 | pty() -- requests a pty\n\ 96 | pty_resize() -- requests a pty resize\n\ 97 | read() -- reads bytes on the channel\n\ 98 | send_eof() -- sends EOF status\n\ 99 | setblocking() -- sets blocking mode\n\ 100 | setenv() -- sets envrionment variable\n\ 101 | shell() -- requests a shell\n\ 102 | window_read() -- checks the status of the read window\n\ 103 | write() -- writes data on a channel\n\ 104 | x11_req() -- requests an X11 Forwarding channel\n\ 105 | "); 106 | 107 | static PyObject * 108 | PYLIBSSH2_Channel(PyObject *self, PyObject *args) 109 | { 110 | PYLIBSSH2_SESSION *session; 111 | int dealloc = 1; 112 | 113 | if (!PyArg_ParseTuple(args, "O|i:Channel", &session, &dealloc)) { 114 | return NULL; 115 | } 116 | 117 | return (PyObject *)PYLIBSSH2_Channel_New(libssh2_channel_open_session( 118 | session->session), dealloc); 119 | } 120 | /* }}} */ 121 | 122 | /* {{{ PYLIBSSH2_Sftp 123 | */ 124 | static char PYLIBSSH2_Sftp_doc[] = "\n\ 125 | \n\ 126 | Arguments:\n\ 127 | \n\ 128 | Returns:\n\ 129 | "; 130 | 131 | static PyObject * 132 | PYLIBSSH2_Sftp(PyObject *self, PyObject *args) 133 | { 134 | PYLIBSSH2_SESSION *session; 135 | int dealloc = 1; 136 | 137 | if (!PyArg_ParseTuple(args, "O|i:Sftp", &session, &dealloc)) { 138 | return NULL; 139 | } 140 | 141 | return (PyObject *)PYLIBSSH2_Sftp_New(libssh2_sftp_init( 142 | session->session), dealloc); 143 | } 144 | /* }}} */ 145 | 146 | /* {{{ PYLIBSSH2_methods[] 147 | */ 148 | static PyMethodDef PYLIBSSH2_methods[] = { 149 | { "Session", (PyCFunction)PYLIBSSH2_Session, METH_VARARGS, PYLIBSSH2_Session_doc }, 150 | { "Channel", (PyCFunction)PYLIBSSH2_Channel, METH_VARARGS, PYLIBSSH2_Channel_doc }, 151 | { "Sftp", (PyCFunction)PYLIBSSH2_Sftp, METH_VARARGS, PYLIBSSH2_Sftp_doc }, 152 | { NULL, NULL } 153 | }; 154 | /* }}} */ 155 | 156 | /* {{{ init_libssh2 157 | */ 158 | PyMODINIT_FUNC 159 | init_libssh2(void) 160 | { 161 | static void *PYLIBSSH2_API[PYLIBSSH2_API_pointers]; 162 | PyObject *c_api_object; 163 | PyObject *module, *dict; 164 | 165 | module = Py_InitModule3( 166 | PYLIBSSH2_MODULE_NAME, 167 | PYLIBSSH2_methods, 168 | PYLIBSSH2_doc 169 | ); 170 | if (module == NULL) { 171 | return; 172 | } 173 | 174 | PYLIBSSH2_API[PYLIBSSH2_Session_New_NUM] = (void *) PYLIBSSH2_Session_New; 175 | PYLIBSSH2_API[PYLIBSSH2_Channel_New_NUM] = (void *) PYLIBSSH2_Channel_New; 176 | PYLIBSSH2_API[PYLIBSSH2_Sftp_New_NUM] = (void *) PYLIBSSH2_Sftp_New; 177 | PYLIBSSH2_API[PYLIBSSH2_Sftphandle_New_NUM] = (void *) PYLIBSSH2_Sftphandle_New; 178 | 179 | c_api_object = PyCObject_FromVoidPtr((void *)PYLIBSSH2_API, NULL); 180 | if (c_api_object != NULL) { 181 | PyModule_AddObject(module, "_C_API", c_api_object); 182 | } 183 | 184 | PYLIBSSH2_Error = PyErr_NewException( 185 | PYLIBSSH2_MODULE_NAME".Error", 186 | NULL, 187 | NULL 188 | ); 189 | if (PYLIBSSH2_Error == NULL) { 190 | goto error; 191 | } 192 | if (PyModule_AddObject(module, "Error", PYLIBSSH2_Error) != 0) { 193 | goto error; 194 | } 195 | 196 | PyModule_AddIntConstant(module, "FINGERPRINT_MD5", 0x0000); 197 | PyModule_AddIntConstant(module, "FINGERPRINT_SHA1", 0x0001); 198 | PyModule_AddIntConstant(module, "FINGERPRINT_HEX", 0x0000); 199 | PyModule_AddIntConstant(module, "FINGERPRINT_RAW", 0x0002); 200 | 201 | PyModule_AddIntConstant(module, "METHOD_KEX", LIBSSH2_METHOD_KEX); 202 | PyModule_AddIntConstant(module, "METHOD_HOSTKEY", LIBSSH2_METHOD_HOSTKEY); 203 | PyModule_AddIntConstant(module, "METHOD_CRYPT_CS", LIBSSH2_METHOD_CRYPT_CS); 204 | PyModule_AddIntConstant(module, "METHOD_CRYPT_SC", LIBSSH2_METHOD_CRYPT_SC); 205 | PyModule_AddIntConstant(module, "METHOD_MAC_CS", LIBSSH2_METHOD_MAC_CS); 206 | PyModule_AddIntConstant(module, "METHOD_MAC_SC", LIBSSH2_METHOD_MAC_SC); 207 | PyModule_AddIntConstant(module, "METHOD_COMP_CS", LIBSSH2_METHOD_COMP_CS); 208 | PyModule_AddIntConstant(module, "METHOD_COMP_SC", LIBSSH2_METHOD_COMP_SC); 209 | 210 | PyModule_AddIntConstant(module, "SFTP_SYMLINK", LIBSSH2_SFTP_SYMLINK); 211 | PyModule_AddIntConstant(module, "SFTP_READLINK", LIBSSH2_SFTP_READLINK); 212 | PyModule_AddIntConstant(module, "SFTP_REALPATH", LIBSSH2_SFTP_REALPATH); 213 | 214 | PyModule_AddIntConstant(module, "SFTP_STAT", LIBSSH2_SFTP_STAT); 215 | PyModule_AddIntConstant(module, "SFTP_LSTAT", LIBSSH2_SFTP_LSTAT); 216 | 217 | PyModule_AddStringConstant(module, "DEFAULT_BANNER", LIBSSH2_SSH_DEFAULT_BANNER); 218 | PyModule_AddStringConstant(module, "LIBSSH2_VERSION", LIBSSH2_VERSION); 219 | 220 | dict = PyModule_GetDict(module); 221 | if (!init_libssh2_Session(dict)) { 222 | goto error; 223 | } 224 | if (!init_libssh2_Channel(dict)) { 225 | goto error; 226 | } 227 | if (!init_libssh2_Sftp(dict)) { 228 | goto error; 229 | } 230 | if (!init_libssh2_Sftphandle(dict)) { 231 | goto error; 232 | } 233 | 234 | error: 235 | ; 236 | } 237 | /* }}} */ 238 | -------------------------------------------------------------------------------- /src/pylibssh2.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_SSH2_H_ 22 | #define _PYLIBSSH2_SSH2_H_ 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "channel.h" 31 | #include "listener.h" 32 | #include "sftp.h" 33 | #include "sftphandle.h" 34 | #include "session.h" 35 | #include "util.h" 36 | 37 | /* pylibssh2 module version */ 38 | #define PYLIBSSH2_VERSION MAJOR_VERSION"."MINOR_VERSION"."PATCH_VERSION 39 | 40 | /* Python module name */ 41 | #define PYLIBSSH2_MODULE_NAME "_libssh2" 42 | 43 | /* Python module's Error */ 44 | extern PyObject *PYLIBSSH2_Error; 45 | 46 | #ifdef exception_from_error_queue 47 | # undef exception_from_error_queue 48 | #endif 49 | #define exception_from_error_queue() do { \ 50 | PyObject *errlist = error_queue_to_list(); \ 51 | PyErr_SetObject(PYLIBSSH2_Error, errlist); \ 52 | Py_DECREF(errlist); \ 53 | } while (0) 54 | 55 | #define PYLIBSSH2_Session_New_NUM 0 56 | #define PYLIBSSH2_Session_New_RETURN PYLIBSSH2_SESSION * 57 | #define PYLIBSSH2_Session_New_PROTO (LIBSSH2_SESSION *, int) 58 | 59 | #define PYLIBSSH2_Channel_New_NUM 1 60 | #define PYLIBSSH2_Channel_New_RETURN PYLIBSSH2_CHANNEL * 61 | #define PYLIBSSH2_Channel_New_PROTO (LIBSSH2_CHANNEL *, int) 62 | 63 | #define PYLIBSSH2_Sftp_New_NUM 2 64 | #define PYLIBSSH2_Sftp_New_RETURN PYLIBSSH2_SFTP * 65 | #define PYLIBSSH2_Sftp_New_PROTO (LIBSSH2_SFTP *, int) 66 | 67 | #define PYLIBSSH2_Sftphandle_New_NUM 3 68 | #define PYLIBSSH2_Sftphandle_New_RETURN PYLIBSSH2_SFTPHANDLE * 69 | #define PYLIBSSH2_Sftphandle_New_PROTO (LIBSSH2_SFTP_HANDLE *, int) 70 | 71 | #define PYLIBSSH2_Listener_New_NUM 4 72 | #define PYLIBSSH2_Listener_New_RETURN PYLIBSSH2_LISTENER * 73 | #define PYLIBSSH2_Listener_New_PROTO (LIBSSH2_LISTENER *, int) 74 | 75 | #define PYLIBSSH2_API_pointers 5 76 | 77 | #ifdef PYLIBSSH2_MODULE 78 | 79 | extern PYLIBSSH2_Session_New_RETURN PYLIBSSH2_Session_New PYLIBSSH2_Session_New_PROTO; 80 | extern PYLIBSSH2_Channel_New_RETURN PYLIBSSH2_Channel_New PYLIBSSH2_Channel_New_PROTO; 81 | extern PYLIBSSH2_Sftp_New_RETURN PYLIBSSH2_Sftp_New PYLIBSSH2_Sftp_New_PROTO; 82 | extern PYLIBSSH2_Sftphandle_New_RETURN PYLIBSSH2_Sftphandle_New PYLIBSSH2_Sftphandle_New_PROTO; 83 | extern PYLIBSSH2_Listener_New_RETURN PYLIBSSH2_Listener_New PYLIBSSH2_Listener_New_PROTO; 84 | 85 | #else 86 | 87 | extern void **PYLIBSSH2_API; 88 | 89 | /*#define PYLIBSSH2_Session_New (*(PYLIBSSH2_Session_New_RETURN (*)PYLIBSSH2_Session_New_PROTO) PYLIBSSH2_API[PYLIBSSH2_Session_New_NUM]) 90 | #define PYLIBSSH2_Channel_New (*(PYLIBSSH2_Channel_New_RETURN (*)PYLIBSSH2_Channel_New_PROTO) PYLIBSSH2_API[PYLIBSSH2_Channel_New_NUM]) 91 | #define PYLIBSSH2_Sftp_New (*(PYLIBSSH2_Sftp_New_RETURN (*)PYLIBSSH2_Sftp_New_PROTO) PYLIBSSH2_API[PYLIBSSH2_Sftp_New_NUM]) 92 | #define PYLIBSSH2_Sftphandle_New (*(PYLIBSSH2_Sftphandle_New_RETURN (*)PYLIBSSH2_Sftphandle_New_PROTO) PYLIBSSH2_API[PYLIBSSH2_Sftphandle_New_NUM]) 93 | #define PYLIBSSH2_Listener_New (*(PYLIBSSH2_Listener_New_RETURN (*)PYLIBSSH2_Listener_New_PROTO) PYLIBSSH2_API[PYLIBSSH2_Listener_New_NUM])*/ 94 | 95 | #define import_PYLIBSSH2() \ 96 | { \ 97 | PyObject *PYLIBSSH2_module = PyImport_ImportModule(PYLIBSSH2_MODULE_NAME); \ 98 | if (PYLIBSSH2_module != NULL) { \ 99 | PyObject *PYLIBSSH2_dict, *PYLIBSSH2_api_object; \ 100 | PYLIBSSH2_dict = PyModule_GetDict(PYLIBSSH2_module); \ 101 | PYLIBSSH2_api_object = PyDict_GetItemString(PYLIBSSH2_dict, "_C_API"); \ 102 | if (PyCObject_Check(PYLIBSSH2_api_object)) { \ 103 | PYLIBSSH2_API = (void **)PyCObject_AsVoidPtr(PYLIBSSH2_api_object); \ 104 | } \ 105 | } \ 106 | } 107 | 108 | #endif /* PYLIBSSH2_MODULE */ 109 | 110 | #endif /* _PYLIBSSH2_SSH2_H_ */ 111 | -------------------------------------------------------------------------------- /src/session.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | /* {{{ PYLIBSSH2_Session_set_banner 26 | */ 27 | static char PYLIBSSH2_Session_set_banner_doc[] = "\ 28 | set_banner(banner) -> int\n\ 29 | \n\ 30 | Sets the banner that will be sent to remote host.\n\ 31 | This is optional, the banner libssh2.DEFAULT_BANNER will be sent by default.\n\ 32 | \n\ 33 | @param banner: an user defined banner\n\ 34 | @type banner: str\n\ 35 | \n\ 36 | @return 0 on success or negative on failure\n\ 37 | @rtype int"; 38 | 39 | static PyObject * 40 | PYLIBSSH2_Session_set_banner(PYLIBSSH2_SESSION *self, PyObject *args) 41 | { 42 | int rc; 43 | char *banner; 44 | 45 | if (!PyArg_ParseTuple(args, "s:set_banner", &banner)) { 46 | return NULL; 47 | } 48 | 49 | rc=libssh2_banner_set(self->session, banner); 50 | 51 | return Py_BuildValue("i", rc); 52 | } 53 | /* }}} */ 54 | 55 | /* {{{ PYLIBSSH2_Session_setblocking 56 | */ 57 | static char PYLIBSSH2_Session_setblocking_doc[] = "\ 58 | setblocking(mode) -> None\n\ 59 | \n\ 60 | Sets blocking mode on session to 0 or 1.\n\ 61 | \n\ 62 | @param mode\n\ 63 | @type int\n\ 64 | \n\ 65 | @return None"; 66 | 67 | static PyObject * 68 | PYLIBSSH2_Session_setblocking(PYLIBSSH2_SESSION *self, PyObject *args) 69 | { 70 | int mode; 71 | 72 | if (!PyArg_ParseTuple(args, "i", &mode)) { 73 | return NULL; 74 | } 75 | 76 | libssh2_session_set_blocking(self->session, mode); 77 | 78 | return Py_BuildValue(""); 79 | } 80 | /* }}} */ 81 | 82 | /* {{{ PYLIBSSH2_Session_getblocking 83 | */ 84 | static char PYLIBSSH2_Session_getblocking_doc[] = "\ 85 | getblocking(mode) -> None\n\ 86 | \n\ 87 | Sets blocking mode on session to 0 or 1.\n\ 88 | \n\ 89 | @return mode\n\ 90 | @type int"; 91 | 92 | static PyObject * 93 | PYLIBSSH2_Session_getblocking(PYLIBSSH2_SESSION *self, PyObject *args) 94 | { 95 | int mode; 96 | 97 | mode = libssh2_session_get_blocking(self->session); 98 | 99 | return Py_BuildValue("i", mode); 100 | } 101 | /* }}} */ 102 | 103 | 104 | /* {{{ PYLIBSSH2_Session_blockdirections 105 | */ 106 | static char PYLIBSSH2_Session_blockdirections_doc[] = "\ 107 | blockdirections() -> blockedon\n\ 108 | \n\ 109 | Returns directions on which session is waiting\n\ 110 | \n\ 111 | \n\ 112 | @return block directions\n\ 113 | @rtype int"; 114 | 115 | static PyObject * 116 | PYLIBSSH2_Session_blockdirections(PYLIBSSH2_SESSION *self, PyObject *args) 117 | { 118 | int blockedon; 119 | 120 | blockedon = libssh2_session_block_directions(self->session); 121 | 122 | return Py_BuildValue("i", blockedon); 123 | } 124 | /* }}} */ 125 | 126 | 127 | 128 | /* {{{ PYLIBSSH2_Session_startup 129 | */ 130 | static char PYLIBSSH2_Session_startup_doc[] = "\ 131 | startup(socket) -> int\n\ 132 | \n\ 133 | Starts up the session from a socket created by socket.socket() call.\n\ 134 | \n\ 135 | @param socket: a connected socket object\n\ 136 | @type socket: socket._socketobject\n\ 137 | \n\ 138 | @return 0 on success or negative on failure\n\ 139 | @rtype int"; 140 | 141 | static PyObject * 142 | PYLIBSSH2_Session_startup(PYLIBSSH2_SESSION *self, PyObject *args) 143 | { 144 | int rc; 145 | int fd; 146 | char *last_error = ""; 147 | PyObject *socket; 148 | 149 | if (!PyArg_ParseTuple(args, "O:startup", &socket)) { 150 | return NULL; 151 | } 152 | 153 | Py_XINCREF(socket); 154 | self->socket = socket; 155 | fd = PyObject_AsFileDescriptor(socket); 156 | Py_BEGIN_ALLOW_THREADS 157 | rc = libssh2_session_handshake(self->session, fd); 158 | Py_END_ALLOW_THREADS 159 | 160 | if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { 161 | libssh2_session_last_error(self->session, &last_error, NULL, 0); 162 | /* CLEAN: PYLIBSSH2_SESSION_STARTUP_MSG */ 163 | PyErr_Format(PYLIBSSH2_Error, "SSH startup: %s", last_error); 164 | return NULL; 165 | } 166 | 167 | if (rc == 0) { 168 | self->opened = 1; 169 | } 170 | 171 | return Py_BuildValue("i", rc); 172 | } 173 | /* }}} */ 174 | 175 | /* {{{ PYLIBSSH2_Session_close 176 | */ 177 | static char PYLIBSSH2_Session_close_doc[] = "\ 178 | close([reason]) -> int \n\ 179 | \n\ 180 | Closes the session.\n\ 181 | \n\ 182 | @param reason: human readable reason for disconnection\n\ 183 | @type reason: str\n\ 184 | \n\ 185 | @return 0 on success or negative on failure\n\ 186 | @rtype int"; 187 | 188 | static PyObject * 189 | PYLIBSSH2_Session_close(PYLIBSSH2_SESSION *self, PyObject *args) 190 | { 191 | int rc; 192 | char *reason = "end"; 193 | 194 | if (!PyArg_ParseTuple(args, "|s:close", &reason)) { 195 | return NULL; 196 | } 197 | 198 | Py_BEGIN_ALLOW_THREADS 199 | rc = libssh2_session_disconnect(self->session, reason); 200 | Py_END_ALLOW_THREADS 201 | 202 | if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { 203 | /* CLEAN: PYLIBSSH2_SESSION_CLOSE_MSG */ 204 | PyErr_SetString(PYLIBSSH2_Error, "SSH close error."); 205 | return NULL; 206 | } 207 | 208 | if (rc == 0) { 209 | self->opened = 0; 210 | } 211 | 212 | return Py_BuildValue("i", rc); 213 | } 214 | /* }}} */ 215 | 216 | /* {{{ PYLIBSSH2_Session_userauth_authenticated 217 | */ 218 | static char PYLIBSSH2_Session_userauth_authenticated_doc[] = "\ 219 | userauth_authenticated() -> int\n\ 220 | \n\ 221 | Returns authentification status for the given session.\n\ 222 | \n\ 223 | @return non-zero if authenticated or 0 if not\n\ 224 | @rtype int"; 225 | 226 | static PyObject * 227 | PYLIBSSH2_Session_userauth_authenticated(PYLIBSSH2_SESSION *self, PyObject *args) 228 | { 229 | return Py_BuildValue("i", libssh2_userauth_authenticated(self->session)); 230 | } 231 | /* }}} */ 232 | 233 | /* {{{ PYLIBSSH2_Session_userauth_list 234 | */ 235 | static char PYLIBSSH2_Session_userauth_list_doc[] = "\ 236 | userauth_list(username) -> str\n\ 237 | \n\ 238 | Lists the authentification methods supported by a server.\n\ 239 | \n\ 240 | @param username: username which will be used while authenticating\n\ 241 | @type username: str\n\ 242 | \n\ 243 | @return a string containing a comma-separated list of authentication methods\n\ 244 | @rtype str"; 245 | 246 | static PyObject * 247 | PYLIBSSH2_Session_userauth_list(PYLIBSSH2_SESSION *self, PyObject *args) 248 | { 249 | char *username; 250 | int username_len = 0; 251 | char *auth_list; 252 | 253 | if (!PyArg_ParseTuple(args, "s#:userauth_list", &username, &username_len)) { 254 | return NULL; 255 | } 256 | 257 | auth_list=libssh2_userauth_list(self->session, username, username_len); 258 | if (auth_list == NULL) { 259 | PyErr_SetString(PYLIBSSH2_Error, "Authentication methods listing failed."); 260 | return NULL; 261 | } 262 | 263 | return PyString_FromString(auth_list); 264 | } 265 | /* }}} */ 266 | 267 | /* {{{ PYLIBSSH2_Session_hostkey_hash 268 | */ 269 | static char PYLIBSSH2_Session_hostkey_hash_doc[] = "\n\ 270 | hostkey_hash([hashtype]) -> str\n\ 271 | \n\ 272 | Returns the computed digest of the remote host's key.\n\ 273 | \n\ 274 | @param hashtype: values possible are 1 (HASH_MD5) or 2 (HASH_SHA1)\n\ 275 | @type hashtype: str\n\ 276 | \n\ 277 | @return string representation of the computed hash value\n\ 278 | @rtype str"; 279 | 280 | static PyObject * 281 | PYLIBSSH2_Session_hostkey_hash(PYLIBSSH2_SESSION *self, PyObject *args) 282 | { 283 | int hashtype = LIBSSH2_HOSTKEY_HASH_MD5; 284 | const char *hash; 285 | 286 | if (!PyArg_ParseTuple(args, "|i:hostkey_hash", &hashtype)) { 287 | return NULL; 288 | } 289 | 290 | Py_BEGIN_ALLOW_THREADS 291 | hash = libssh2_hostkey_hash(self->session, hashtype); 292 | Py_END_ALLOW_THREADS 293 | 294 | if (hash == NULL) { 295 | Py_INCREF(Py_None); 296 | return Py_None; 297 | } 298 | 299 | return PyString_FromString(hash); 300 | } 301 | /* }}} */ 302 | 303 | /* {{{ PYLIBSSH2_Session_userauth_password 304 | */ 305 | static char PYLIBSSH2_Session_userauth_password_doc[] = "\n\ 306 | userauth_password(username, password) -> int \n\ 307 | \n\ 308 | Authenticates a session with the given username and password.\n\ 309 | \n\ 310 | @param username: user to authenticate\n\ 311 | @type username: str\n\ 312 | @param password: password to use for the authentication\n\ 313 | @type password: str\n\ 314 | \n\ 315 | @return 0 on success or raise an exception on failure\n\ 316 | @rtype int"; 317 | 318 | static PyObject * 319 | PYLIBSSH2_Session_userauth_password(PYLIBSSH2_SESSION *self, PyObject *args) 320 | { 321 | int rc; 322 | char *username; 323 | char *password; 324 | 325 | if (!PyArg_ParseTuple(args, "ss:userauth_password", &username, &password)) 326 | return NULL; 327 | 328 | Py_BEGIN_ALLOW_THREADS 329 | rc = libssh2_userauth_password_ex(self->session, username, strlen(username), password, strlen(password), NULL); 330 | Py_END_ALLOW_THREADS 331 | 332 | if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { 333 | /* CLEAN: PYLIBSSH2_SESSION_USERAUTH_PASSWORD_FAILED_MSG */ 334 | PyErr_SetString(PYLIBSSH2_Error, "Authentification by password failed."); 335 | return NULL; 336 | } 337 | 338 | return Py_BuildValue("i", rc); 339 | } 340 | /* }}} */ 341 | 342 | /* {{{ PYLIBSSH2_Session_userauth_publickey_fromfile 343 | */ 344 | static char PYLIBSSH2_Session_userauth_publickey_fromfile_doc[] = "\n\ 345 | userauth_publickey_fromfile(username, publickey, privatekey, passphrase) -> int\n\ 346 | \n\ 347 | Authenticates a session as username using a key pair found in the pulickey and\n\ 348 | privatekey files, and passphrase if provided.\n\ 349 | \n\ 350 | @param username: user to authenticate\n\ 351 | @type username: str\n\ 352 | @param publickey: path and name of public key file\n\ 353 | @type publickey: str\n\ 354 | @param privatekey: path and name of private key file\n\ 355 | @type privatekey: str\n\ 356 | @param passphrase: passphrase to use when decoding private file\n\ 357 | @type passphrase: str\n\ 358 | \n\ 359 | @return 0 on success or negative on failure\n\ 360 | @rtype int"; 361 | 362 | static PyObject * 363 | PYLIBSSH2_Session_userauth_publickey_fromfile(PYLIBSSH2_SESSION *self, PyObject *args) 364 | { 365 | int rc; 366 | char *username; 367 | char *publickey; 368 | char *privatekey; 369 | char *passphrase; 370 | char *last_error; 371 | 372 | if (!PyArg_ParseTuple(args, "szs|z:userauth_publickey_fromfile", &username, 373 | &publickey, &privatekey, &passphrase)) { 374 | return NULL; 375 | } 376 | 377 | Py_BEGIN_ALLOW_THREADS 378 | rc = libssh2_userauth_publickey_fromfile(self->session, username, publickey, 379 | privatekey, passphrase); 380 | Py_END_ALLOW_THREADS 381 | 382 | if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { 383 | libssh2_session_last_error(self->session, &last_error, NULL, 0); 384 | PyErr_Format(PYLIBSSH2_Error, "Authentification by public key failed: %s", 385 | last_error); 386 | return NULL; 387 | } 388 | 389 | return Py_BuildValue("i", rc); 390 | } 391 | /* }}} */ 392 | 393 | /* {{{ PYLIBSSH2_Session_userauth_agent 394 | */ 395 | static char PYLIBSSH2_Session_userauth_agent_doc[] = "\n\ 396 | userauth_agent(username) -> int\n\ 397 | \n\ 398 | Authenticates a session as username using a ssh-agent\n\ 399 | \n\ 400 | @param username: user to authenticate\n\ 401 | @type username: str\n\ 402 | \n\ 403 | @return 0 on success or negative on failure\n\ 404 | @rtype int"; 405 | 406 | static PyObject * 407 | PYLIBSSH2_Session_userauth_agent(PYLIBSSH2_SESSION *self, PyObject *args) 408 | { 409 | struct libssh2_agent_publickey * identity = NULL; 410 | struct libssh2_agent_publickey * prev_identity = NULL; 411 | LIBSSH2_AGENT * agent = NULL; 412 | char * last_error = NULL; 413 | char * error_message = "Something went wrong..."; 414 | char * username = NULL; 415 | int rc = 1; 416 | 417 | if (!PyArg_ParseTuple(args, "s", &username)) { 418 | return NULL; 419 | } 420 | 421 | Py_BEGIN_ALLOW_THREADS 422 | //printf("[DEBUG] userauth_agent(): Py_BEGIN_ALLOW_THREADS\n"); 423 | agent = libssh2_agent_init(self->session); 424 | if (!agent) { 425 | error_message = "Failure initializing ssh-agent support"; 426 | goto shutdown; 427 | } 428 | //printf("[DEBUG] userauth_agent(): agent_init() OK\n"); 429 | if (libssh2_agent_connect(agent)) { 430 | error_message = "Failure connecting to ssh-agent"; 431 | goto shutdown; 432 | } 433 | //printf("[DEBUG] userauth_agent(): agent_connect() OK\n"); 434 | if (libssh2_agent_list_identities(agent)) { 435 | error_message = "Failure requesting identities to ssh-agent"; 436 | goto shutdown; 437 | } 438 | //printf("[DEBUG] userauth_agent(): agent_list_identities() OK\n"); 439 | while (1) { 440 | rc = libssh2_agent_get_identity(agent, &identity, prev_identity); 441 | 442 | if (rc == 1) 443 | break; 444 | if (rc < 0) { 445 | error_message = "Failure obtaining identity from ssh-agent support"; 446 | goto shutdown; 447 | } 448 | //printf("[DEBUG] userauth_agent(): agent_get_identity() OK\n"); 449 | if (!libssh2_agent_userauth(agent, username, identity)) { 450 | // Authentication succeed! 451 | break; 452 | } 453 | error_message = "No authorized key found in ssh-agent!"; 454 | prev_identity = identity; 455 | } 456 | shutdown: 457 | //printf("[DEBUG] userauth_agent(): shutdown...\n"); 458 | if (agent) { 459 | libssh2_agent_disconnect(agent); 460 | libssh2_agent_free(agent); 461 | } 462 | 463 | Py_END_ALLOW_THREADS 464 | //printf("[DEBUG] userauth_agent(): Py_END_ALLOW_THREADS\n"); 465 | 466 | if (rc) { 467 | libssh2_session_last_error(self->session, &last_error, NULL, 0); 468 | PyErr_Format(PYLIBSSH2_Error, "Authentification by public key failed: %s (%s)", 469 | error_message, 470 | last_error); 471 | return NULL; 472 | } 473 | 474 | return Py_BuildValue("i", rc); 475 | } 476 | /* }}} */ 477 | 478 | 479 | /* {{{ PYLIBSSH2_Session_session_methods 480 | */ 481 | static char PYLIBSSH2_Session_session_methods_doc[] = "\n\ 482 | session_methods() -> dict\n\ 483 | \n\ 484 | Returns a dictionnary with the currently active algorithms. \n\ 485 | CS keys is Client to Server and SC keys is Server to Client.\n\ 486 | \n\ 487 | @return a dictionnary with actual method neogicated\n\ 488 | @rtype dict"; 489 | 490 | static PyObject * 491 | PYLIBSSH2_Session_session_methods(PYLIBSSH2_SESSION *self, PyObject *args) 492 | { 493 | /* cs = client-server, sc = server-client */ 494 | const char *kex, *hostkey; 495 | const char *crypt_cs, *crypt_sc; 496 | const char *mac_cs, *mac_sc; 497 | const char *comp_cs, *comp_sc; 498 | const char *lang_cs, *lang_sc; 499 | 500 | PyObject *methods; 501 | 502 | kex = libssh2_session_methods(self->session, LIBSSH2_METHOD_KEX); 503 | if (kex == NULL) { 504 | /* session has not yet been started no methods negociated */ 505 | Py_INCREF(Py_None); 506 | return Py_None; 507 | } 508 | hostkey = libssh2_session_methods(self->session, LIBSSH2_METHOD_HOSTKEY); 509 | crypt_cs = libssh2_session_methods(self->session, LIBSSH2_METHOD_CRYPT_CS); 510 | crypt_sc = libssh2_session_methods(self->session, LIBSSH2_METHOD_CRYPT_SC); 511 | mac_cs = libssh2_session_methods(self->session, LIBSSH2_METHOD_MAC_CS); 512 | mac_sc = libssh2_session_methods(self->session, LIBSSH2_METHOD_MAC_SC); 513 | comp_cs = libssh2_session_methods(self->session, LIBSSH2_METHOD_COMP_CS); 514 | comp_sc = libssh2_session_methods(self->session, LIBSSH2_METHOD_COMP_SC); 515 | lang_cs = libssh2_session_methods(self->session, LIBSSH2_METHOD_LANG_CS); 516 | lang_sc = libssh2_session_methods(self->session, LIBSSH2_METHOD_LANG_SC); 517 | 518 | /* create a python dictionnary to store cryptographic algorithms */ 519 | methods = PyDict_New(); 520 | PyDict_SetItemString(methods, "KEX", PyString_FromString(kex)); 521 | PyDict_SetItemString(methods, "HOSTKEY", PyString_FromString(hostkey)); 522 | PyDict_SetItemString(methods, "CRYPT_CS", PyString_FromString(crypt_cs)); 523 | PyDict_SetItemString(methods, "CRYPT_SC", PyString_FromString(crypt_sc)); 524 | PyDict_SetItemString(methods, "MAC_CS", PyString_FromString(mac_cs)); 525 | PyDict_SetItemString(methods, "MAC_SC", PyString_FromString(mac_sc)); 526 | PyDict_SetItemString(methods, "COMP_CS", PyString_FromString(comp_cs)); 527 | PyDict_SetItemString(methods, "COMP_SC", PyString_FromString(comp_sc)); 528 | PyDict_SetItemString(methods, "LANG_CS", PyString_FromString(lang_cs)); 529 | PyDict_SetItemString(methods, "LANG_SC", PyString_FromString(lang_sc)); 530 | 531 | return methods; 532 | } 533 | /* }}} */ 534 | 535 | /* {{{ PYLIBSSH2_Session_session_method_pref 536 | */ 537 | static char PYLIBSSH2_Session_session_method_pref_doc[] = "\n\ 538 | session_method_pref(method_type, pref) -> int\n\ 539 | \n\ 540 | Sets preferred methods to be negociated. Theses preferences must be\n\ 541 | prior to calling startup().\n\ 542 | \n\ 543 | @param method_type: the method type constants\n\ 544 | @type method_type: L{libssh2.METHOD}\n\ 545 | @param pref: coma delimited list of preferred methods\n\ 546 | @type pref: str\n\ 547 | \n\ 548 | @return 0 on success or negative on failure\n\ 549 | @rtype int"; 550 | 551 | static PyObject * 552 | PYLIBSSH2_Session_session_method_pref(PYLIBSSH2_SESSION *self, PyObject *args) 553 | { 554 | int method; 555 | char *pref; 556 | 557 | if (!PyArg_ParseTuple(args, "is:session_method_pref", &method, &pref)) { 558 | return NULL; 559 | } 560 | 561 | return PyInt_FromLong(libssh2_session_method_pref(self->session, method, pref)==0?1:0); 562 | } 563 | /* }}} */ 564 | 565 | /* {{{ PYLIBSSH2_Session_open_session 566 | */ 567 | static char PYLIBSSH2_Session_open_session_doc[] = "\n\ 568 | open_session() -> libssh2.Channel\n\ 569 | \n\ 570 | Allocates a new channel for the current session.\n\ 571 | \n\ 572 | @return new channel opened\n\ 573 | @rtype libssh2.Channel"; 574 | 575 | static PyObject * 576 | PYLIBSSH2_Session_open_session(PYLIBSSH2_SESSION *self, PyObject *args) 577 | { 578 | int dealloc = 1; 579 | LIBSSH2_CHANNEL *channel; 580 | 581 | if (!PyArg_ParseTuple(args, "|i:open_session", &dealloc)) { 582 | return NULL; 583 | } 584 | 585 | channel = libssh2_channel_open_session(self->session); 586 | 587 | if (channel== NULL){ 588 | if (libssh2_session_last_error(self->session,NULL,NULL,0) == 589 | LIBSSH2_ERROR_EAGAIN){ 590 | return Py_BuildValue(""); 591 | } 592 | else{ 593 | PyErr_SetString(PYLIBSSH2_Error, "Failed to open channel"); 594 | return NULL; 595 | } 596 | } 597 | else { 598 | return (PyObject *)PYLIBSSH2_Channel_New(channel, dealloc); 599 | } 600 | } 601 | /* }}} */ 602 | 603 | /* {{{ PYLIBSSH2_Session_scp_recv 604 | */ 605 | static char PYLIBSSH2_Session_scp_recv_doc[] = "\n\ 606 | scp_recv(remote_path) -> libssh2.Channel\n\ 607 | \n\ 608 | Requests a remote file via SCP protocol.\n\ 609 | \n\ 610 | @param remote_path: absolute path of remote file to transfer\n\ 611 | @type remote_path: str\n\ 612 | \n\ 613 | @return new channel opened\n\ 614 | @rtype libssh2.Channel"; 615 | 616 | static PyObject * 617 | PYLIBSSH2_Session_scp_recv(PYLIBSSH2_SESSION *self, PyObject *args) 618 | { 619 | char *path; 620 | LIBSSH2_CHANNEL *channel; 621 | 622 | if (!PyArg_ParseTuple(args, "s:scp_recv", &path)) { 623 | return NULL; 624 | } 625 | 626 | channel = libssh2_scp_recv(self->session, path, NULL); 627 | if (channel == NULL) { 628 | /* CLEAN: PYLIBSSH2_CHANNEL_SCP_RECV_ERROR_MSG */ 629 | PyErr_SetString(PYLIBSSH2_Error, "SCP receive error."); 630 | return NULL; 631 | } 632 | 633 | return (PyObject *)PYLIBSSH2_Channel_New(channel, 1); 634 | } 635 | /* }}} */ 636 | 637 | /* {{{ PYLIBSSH2_Session_scp_send 638 | */ 639 | static char PYLIBSSH2_Session_scp_send_doc[] = "\n\ 640 | scp_send(path, mode, size) -> libssh2.Channel\n\ 641 | \n\ 642 | Sends a file to remote host via SCP protocol.\n\ 643 | \n\ 644 | @param path: absolute path of tile to transfer\n\ 645 | @type path: str\n\ 646 | @param mode: file access mode to create file\n\ 647 | @type mode: int\n\ 648 | @param size: size of file being transmitted\n\ 649 | @type size: int\n\ 650 | \n\ 651 | @return new channel opened\n\ 652 | @rtype libssh2.Channel"; 653 | 654 | static PyObject * 655 | PYLIBSSH2_Session_scp_send(PYLIBSSH2_SESSION *self, PyObject *args) 656 | { 657 | char *path; 658 | int mode; 659 | unsigned long filesize; 660 | LIBSSH2_CHANNEL *channel; 661 | 662 | if (!PyArg_ParseTuple(args, "sik:scp_send", &path, &mode, &filesize)) { 663 | return NULL; 664 | } 665 | 666 | channel = libssh2_scp_send(self->session, path, mode, filesize); 667 | if (channel == NULL) { 668 | /* CLEAN: PYLIBSSH2_CHANNEL_SCP_SEND_ERROR_MSG */ 669 | PyErr_SetString(PYLIBSSH2_Error, "SCP send error."); 670 | return NULL; 671 | } 672 | 673 | return (PyObject *)PYLIBSSH2_Channel_New(channel, 1); 674 | } 675 | /* }}} */ 676 | 677 | /* {{{ PYLIBSSH2_Session_sftp_init 678 | */ 679 | static char PYLIBSSH2_Session_sftp_init_doc[] = "\n\ 680 | sftp_init() -> libssh2.Sftp\n\ 681 | \n\ 682 | Opens an SFTP Channel.\n\ 683 | \n\ 684 | @return new opened SFTP channel\n\ 685 | @rtype libssh2.Sftp"; 686 | 687 | static PyObject * 688 | PYLIBSSH2_Session_sftp_init(PYLIBSSH2_SESSION *self, PyObject *args) 689 | { 690 | int dealloc = 1; 691 | 692 | if (!PyArg_ParseTuple(args, "|i:sftp_init", &dealloc)) { 693 | return NULL; 694 | } 695 | 696 | return (PyObject *)PYLIBSSH2_Sftp_New(libssh2_sftp_init(self->session), dealloc); 697 | } 698 | /* }}} */ 699 | 700 | /* {{{ PYLIBSSH2_Session_direct_tcpip 701 | */ 702 | static char PYLIBSSH2_Session_direct_tcpip_doc[] = "\n\ 703 | direct_tcpip(host, port, shost, sport) -> libssh2.Channel\n\ 704 | \n\ 705 | Tunnels a TCP connection through an SSH Session.\n\ 706 | \n\ 707 | @param host: remote host\n\ 708 | @type host: str\n\ 709 | @param port: remote port\n\ 710 | @type port: int\n\ 711 | @param shost: local host\n\ 712 | @type shost: str\n\ 713 | @param sport: local port\n\ 714 | @type sport: int\n\ 715 | \n\ 716 | @return new opened channel\n\ 717 | @rtype libssh2.Channel"; 718 | 719 | static PyObject * 720 | PYLIBSSH2_Session_direct_tcpip(PYLIBSSH2_SESSION *self, PyObject *args) 721 | { 722 | /* remote host */ 723 | char *host; 724 | /* local host */ 725 | char *shost = "127.0.0.1"; 726 | /* local port */ 727 | int sport = 22; 728 | /* remote port */ 729 | int port; 730 | LIBSSH2_CHANNEL *channel; 731 | char *last_error = ""; 732 | 733 | if (!PyArg_ParseTuple(args, "si|si:direct_tcpip", &host, &port, &shost, &sport)) { 734 | return NULL; 735 | } 736 | 737 | Py_BEGIN_ALLOW_THREADS 738 | channel = libssh2_channel_direct_tcpip_ex(self->session, host, port, shost, sport); 739 | Py_END_ALLOW_THREADS 740 | 741 | if (channel == NULL) { 742 | libssh2_session_last_error(self->session, &last_error, NULL, 0); 743 | /* CLEAN: PYLIBSSH2_SESSION_TCP_CONNECT_ERROR_MSG */ 744 | PyErr_SetString(PYLIBSSH2_Error, "Unable to create TCP connection."); 745 | return NULL; 746 | } 747 | 748 | return (PyObject *)channel; 749 | } 750 | /* }}} */ 751 | 752 | /* {{{ PYLIBSSH2_Session_forward_listen 753 | */ 754 | static char PYLIBSSH2_Session_forward_listen_doc[] = "\n\ 755 | forward_listen(host, port, bound_port, queue_maxsize) -> libssh2.Listener\n\ 756 | \n\ 757 | Forwards a TCP connection through an SSH Session.\n\ 758 | \n\ 759 | @param host: remote host\n\ 760 | @type host: str\n\ 761 | @param port: remote port\n\ 762 | @type port: int\n\ 763 | @param bound_port: populated with the actual port on the remote host\n\ 764 | @type bound_port: int\n\ 765 | @param queue_maxsize: maximum number of pending connections\n\ 766 | @type int\n\ 767 | \n\ 768 | @return new libssh2.Listener instance on succes or None on failure\n\ 769 | @rtype libssh2.Listener"; 770 | 771 | static PyObject * 772 | PYLIBSSH2_Session_forward_listen(PYLIBSSH2_SESSION *self, PyObject *args) 773 | { 774 | char *host; 775 | int port; 776 | int queue_maxsize; 777 | int *bound_port; 778 | LIBSSH2_LISTENER *listener; 779 | 780 | if (!PyArg_ParseTuple(args, "siii:forward_listen", &host, &port, 781 | &bound_port, &queue_maxsize)) { 782 | return NULL; 783 | } 784 | 785 | Py_BEGIN_ALLOW_THREADS 786 | listener = libssh2_channel_forward_listen_ex(self->session, host, port, 787 | bound_port, queue_maxsize); 788 | Py_END_ALLOW_THREADS 789 | 790 | if (listener == NULL) { 791 | /* CLEAN: PYLIBSSH2_SESSION_TCP_CONNECT_ERROR_MSG */ 792 | PyErr_SetString(PYLIBSSH2_Error, "Unable to forward listen connection."); 793 | return NULL; 794 | } 795 | 796 | return (PyObject *)PYLIBSSH2_Listener_New(listener, 0); 797 | } 798 | /* }}} */ 799 | 800 | /* {{{ PYLIBSSH2_Session_last_error 801 | */ 802 | static char PYLIBSSH2_Session_last_error_doc[] = "\n\ 803 | last_error() -> (int, str)\n\ 804 | \n\ 805 | Returns the last error in tuple format (code, message).\n\ 806 | \n\ 807 | @return error tuple (int, str)\n\ 808 | @rtype tuple"; 809 | 810 | static PyObject * 811 | PYLIBSSH2_Session_last_error(PYLIBSSH2_SESSION *self, PyObject *args) 812 | { 813 | char *errmsg; 814 | int rc,want_buf=0; 815 | 816 | Py_BEGIN_ALLOW_THREADS 817 | rc=libssh2_session_last_error(self->session, &errmsg, NULL, want_buf); 818 | Py_END_ALLOW_THREADS 819 | 820 | return Py_BuildValue("(i,s)", rc, errmsg); 821 | } 822 | /* }}} */ 823 | 824 | /* {{{ PYLIBSSH2_Session_callback_set 825 | */ 826 | static char PYLIBSSH2_Session_callback_set_doc[] = "\n\ 827 | callback_set(cbtype, callback)\n\ 828 | \n\ 829 | Set (or reset) a callback function\n\ 830 | \n\ 831 | @param cbtype\n\ 832 | @param callback\n\ 833 | @return\n\ 834 | @rtype "; 835 | 836 | /* 837 | void 838 | x11_callback(LIBSSH2_SESSION *session, LIBSSH2_CHANNEL *channel, 839 | const char *shost, int sport, void **abstract) 840 | */ 841 | 842 | static PyObject *py_callback_func = NULL; 843 | 844 | static void 845 | stub_callback_func(LIBSSH2_SESSION *session, 846 | LIBSSH2_CHANNEL *channel, 847 | const char *shost, 848 | int sport, 849 | void **abstract) 850 | { 851 | int rc=0; 852 | 853 | PYLIBSSH2_SESSION *pysession; 854 | PYLIBSSH2_CHANNEL *pychannel; 855 | PyObject *pyabstract; 856 | 857 | /* Ensure current thread is ready to call Python C API */ 858 | PyGILState_STATE gstate; 859 | gstate = PyGILState_Ensure(); 860 | 861 | PyObject *arglist; 862 | PyObject *result = NULL; 863 | 864 | pysession = PyObject_New(PYLIBSSH2_SESSION, &PYLIBSSH2_Session_Type); 865 | pysession->session = session; 866 | pysession->opened = 1; 867 | pysession->dealloc = 0; 868 | Py_INCREF(pysession); 869 | 870 | pychannel = PyObject_New(PYLIBSSH2_CHANNEL, &PYLIBSSH2_Channel_Type); 871 | pychannel->channel = channel; 872 | pychannel->dealloc = 0; 873 | Py_INCREF(pychannel); 874 | 875 | pyabstract = Py_None; 876 | Py_INCREF(pyabstract); 877 | 878 | arglist = Py_BuildValue("(OOsiO)", 879 | pysession, pychannel, shost, sport, pyabstract 880 | ); 881 | Py_INCREF(arglist); 882 | 883 | /* Performing Python callback with C API */ 884 | result = PyEval_CallObject(py_callback_func, arglist); 885 | if (result && PyInt_Check(result)) { 886 | rc = PyInt_AsLong(result); 887 | } 888 | 889 | /* Restore previous thread state and release acquired resources */ 890 | PyGILState_Release(gstate); 891 | 892 | Py_DECREF(pysession); 893 | Py_DECREF(pychannel); 894 | Py_DECREF(pyabstract); 895 | Py_DECREF(arglist); 896 | } 897 | 898 | static PyObject * 899 | PYLIBSSH2_Session_callback_set(PYLIBSSH2_SESSION *self, PyObject *args) 900 | { 901 | PyObject *result = NULL; 902 | 903 | /* type of callback to register see libssh2.h LIBSSH2_CALLBACK_* */ 904 | int cbtype; 905 | 906 | /* callback is callable Python Object */ 907 | PyObject *cb; 908 | 909 | if (PyArg_ParseTuple(args, "iO:callback_set", &cbtype, &cb)) { 910 | if (!PyCallable_Check(cb)) { 911 | PyErr_SetString(PyExc_TypeError, "parameter must be callable"); 912 | return NULL; 913 | } 914 | 915 | Py_XINCREF(cb); 916 | Py_XINCREF(py_callback_func); 917 | py_callback_func = cb; 918 | 919 | Py_BEGIN_ALLOW_THREADS 920 | libssh2_session_callback_set(self->session, cbtype, stub_callback_func); 921 | Py_END_ALLOW_THREADS 922 | 923 | Py_INCREF(Py_None); 924 | result = Py_None; 925 | } 926 | 927 | return result; 928 | } 929 | /* }}} */ 930 | 931 | /* {{{ PYLIBSSH2_Session_set_trace 932 | */ 933 | static char PYLIBSSH2_Session_set_trace_doc[] = "\n\ 934 | set_trace(bitmask)\n\ 935 | \n\ 936 | Set the trace level\n\ 937 | \n\ 938 | @param bitmask\n\ 939 | @return\n\ 940 | @rtype "; 941 | 942 | static PyObject * 943 | PYLIBSSH2_Session_set_trace(PYLIBSSH2_SESSION *self, PyObject *args) 944 | { 945 | int rc=0; 946 | int bitmask; 947 | 948 | if (!PyArg_ParseTuple(args, "i:set_trace", &bitmask)) { 949 | return NULL; 950 | } 951 | 952 | Py_BEGIN_ALLOW_THREADS 953 | libssh2_trace(self->session, bitmask); 954 | Py_END_ALLOW_THREADS 955 | 956 | return Py_BuildValue("i", rc); 957 | } 958 | /* }}} */ 959 | 960 | /* 961 | void 962 | kbd_callback(const char *name, int name_len, const char *instruction, 963 | int instruction_len, int num_prompts, 964 | const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, 965 | LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract) 966 | static PyObject *kbd_callback_func = NULL; 967 | */ 968 | 969 | static char *interactive_response; 970 | static int interactive_response_len; 971 | 972 | static void 973 | stub_kbd_callback_func(const char *name, int name_len, 974 | const char *instruction, int instruction_len, 975 | int num_prompts, 976 | const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, 977 | LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, 978 | void **abstract) 979 | { 980 | int i; 981 | (void)abstract; 982 | 983 | for (i=0; i < num_prompts; i++) { 984 | responses[i].text = strdup(interactive_response); 985 | responses[i].length = interactive_response_len; 986 | } 987 | } 988 | 989 | /* {{{ PYLIBSSH2_Session_userauth_keyboardinteractive 990 | */ 991 | static char PYLIBSSH2_Session_userauth_keyboardinteractive_doc[] = "\n\ 992 | userauth_keyboardinteractive(username)\n\ 993 | \n\ 994 | Authenticate a session using a challenge-response authentication\n\ 995 | \n\ 996 | @param username: name of user to attempt authentication\n\ 997 | @return 0 on success or negative on failure\n\ 998 | @rtype "; 999 | 1000 | /* {{{ PYLIBSSH2_Session_userauth_keyboardinteractive 1001 | */ 1002 | static PyObject * 1003 | PYLIBSSH2_Session_userauth_keyboardinteractive(PYLIBSSH2_SESSION *self, PyObject *args) 1004 | { 1005 | int rc=0; 1006 | char *username; 1007 | /*PyObject *kbd_callback;*/ 1008 | 1009 | if(!PyArg_ParseTuple(args, "ssi:userauth_keyboardinteractive", &username, &interactive_response, &interactive_response_len)) { 1010 | return NULL; 1011 | } 1012 | 1013 | Py_BEGIN_ALLOW_THREADS 1014 | rc = libssh2_userauth_keyboard_interactive(self->session, username, &stub_kbd_callback_func); 1015 | Py_END_ALLOW_THREADS 1016 | 1017 | if (rc < 0 && rc != LIBSSH2_ERROR_EAGAIN) { 1018 | PyErr_SetString(PYLIBSSH2_Error, "Authentication by keyboard-interactive failed."); 1019 | return NULL; 1020 | } 1021 | 1022 | return Py_BuildValue("i", rc); 1023 | 1024 | } 1025 | 1026 | /* }}} */ 1027 | 1028 | /* {{{ PYLIBSSH2_Session_methods[] 1029 | * 1030 | * ADD_METHOD(name) expands to a correct PyMethodDef declaration 1031 | * { 'name', (PyCFunction)PYLIBSSH2_Session_name, METHOD_VARARGS } 1032 | * for convenience 1033 | * 1034 | */ 1035 | #define ADD_METHOD(name) \ 1036 | { #name, (PyCFunction)PYLIBSSH2_Session_##name, METH_VARARGS, PYLIBSSH2_Session_##name##_doc } 1037 | 1038 | static PyMethodDef PYLIBSSH2_Session_methods[] = 1039 | { 1040 | ADD_METHOD(set_banner), 1041 | ADD_METHOD(setblocking), 1042 | ADD_METHOD(getblocking), 1043 | ADD_METHOD(blockdirections), 1044 | ADD_METHOD(startup), 1045 | ADD_METHOD(close), 1046 | ADD_METHOD(userauth_authenticated), 1047 | ADD_METHOD(hostkey_hash), 1048 | ADD_METHOD(userauth_list), 1049 | ADD_METHOD(session_methods), 1050 | ADD_METHOD(userauth_password), 1051 | ADD_METHOD(userauth_publickey_fromfile), 1052 | ADD_METHOD(session_method_pref), 1053 | ADD_METHOD(open_session), 1054 | ADD_METHOD(scp_recv), 1055 | ADD_METHOD(scp_send), 1056 | ADD_METHOD(sftp_init), 1057 | ADD_METHOD(direct_tcpip), 1058 | ADD_METHOD(forward_listen), 1059 | ADD_METHOD(last_error), 1060 | ADD_METHOD(callback_set), 1061 | ADD_METHOD(set_trace), 1062 | ADD_METHOD(userauth_keyboardinteractive), 1063 | ADD_METHOD(userauth_agent), 1064 | { NULL, NULL } 1065 | }; 1066 | #undef ADD_METHOD 1067 | /* }}} */ 1068 | 1069 | /* {{{ PYLIBSSH2_Session_New 1070 | */ 1071 | PYLIBSSH2_SESSION * 1072 | PYLIBSSH2_Session_New(LIBSSH2_SESSION *session, int dealloc) 1073 | { 1074 | PYLIBSSH2_SESSION *self; 1075 | 1076 | self = PyObject_New(PYLIBSSH2_SESSION, &PYLIBSSH2_Session_Type); 1077 | 1078 | if (self == NULL) { 1079 | return NULL; 1080 | } 1081 | 1082 | self->session = session; 1083 | self->dealloc = dealloc; 1084 | self->opened = 0; 1085 | self->socket = NULL; 1086 | 1087 | libssh2_banner_set(session, LIBSSH2_SSH_DEFAULT_BANNER " Python"); 1088 | 1089 | return self; 1090 | } 1091 | /* }}} */ 1092 | 1093 | /* {{{ PYLIBSSH2_Session_dealloc 1094 | */ 1095 | static void 1096 | PYLIBSSH2_Session_dealloc(PYLIBSSH2_SESSION *self) 1097 | { 1098 | if (self->opened) { 1099 | libssh2_session_disconnect(self->session, "end"); 1100 | } 1101 | 1102 | if (self->dealloc) { 1103 | libssh2_session_free(self->session); 1104 | } 1105 | 1106 | Py_XDECREF(self->socket); 1107 | self->socket = NULL; 1108 | 1109 | if (self) { 1110 | PyObject_Del(self); 1111 | } 1112 | } 1113 | /* }}} */ 1114 | 1115 | /* {{{ PYLIBSSH2_Session_getattr 1116 | */ 1117 | static PyObject * 1118 | PYLIBSSH2_Session_getattr(PYLIBSSH2_SESSION *self, char *name) 1119 | { 1120 | return Py_FindMethod(PYLIBSSH2_Session_methods, (PyObject *)self, name); 1121 | } 1122 | /* }}} */ 1123 | 1124 | /* {{{ PYLIBSSH2_Session_Type 1125 | * 1126 | * see /usr/include/python2.5/object.h line 261 1127 | */ 1128 | PyTypeObject PYLIBSSH2_Session_Type = { 1129 | PyObject_HEAD_INIT(NULL) 1130 | 0, /* ob_size */ 1131 | "Session", /* tp_name */ 1132 | sizeof(PYLIBSSH2_SESSION), /* tp_basicsize */ 1133 | 0, /* tp_itemsize */ 1134 | (destructor)PYLIBSSH2_Session_dealloc, /* tp_dealloc */ 1135 | 0, /* tp_print */ 1136 | (getattrfunc)PYLIBSSH2_Session_getattr, /* tp_getattr */ 1137 | 0, /* tp_setattr */ 1138 | 0, /* tp_compare */ 1139 | 0, /* tp_repr */ 1140 | 0, /* tp_as_number */ 1141 | 0, /* tp_as_sequence */ 1142 | 0, /* tp_as_mapping */ 1143 | 0, /* tp_hash */ 1144 | 0, /* tp_call */ 1145 | 0, /* tp_str */ 1146 | 0, /* tp_getattro */ 1147 | 0, /* tp_setattro */ 1148 | 0, /* tp_as_buffer */ 1149 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 1150 | "Sesssion objects", /* tp_doc */ 1151 | }; 1152 | /* }}} */ 1153 | 1154 | /* {{{ init_libssh2_Session 1155 | */ 1156 | int 1157 | init_libssh2_Session(PyObject *dict) 1158 | { 1159 | PYLIBSSH2_Session_Type.ob_type = &PyType_Type; 1160 | Py_XINCREF(&PYLIBSSH2_Session_Type); 1161 | PyDict_SetItemString(dict, "SessionType", (PyObject *)&PYLIBSSH2_Session_Type); 1162 | 1163 | return 1; 1164 | } 1165 | -------------------------------------------------------------------------------- /src/session.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_SESSION_H_ 22 | #define _PYLIBSSH2_SESSION_H_ 23 | 24 | #include 25 | #include 26 | 27 | extern int init_libssh2_Session(PyObject *); 28 | 29 | extern PyTypeObject PYLIBSSH2_Session_Type; 30 | 31 | #define PYLIBSSH2_Session_Check(v) ((v)->ob_type == &PYLIBSSH2_Session_Type) 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | LIBSSH2_SESSION *session; 36 | PyObject *socket; 37 | int dealloc; 38 | int opened; 39 | } PYLIBSSH2_SESSION; 40 | 41 | #endif /* _PYLIBSSH2_SESSION_H_ */ 42 | -------------------------------------------------------------------------------- /src/sftp.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | /* {{{ get_attrs 26 | */ 27 | PyObject * 28 | get_attrs(LIBSSH2_SFTP_ATTRIBUTES *attr) 29 | { 30 | PyObject *attrs=NULL; 31 | 32 | attrs = PyList_New(0); 33 | PyList_Append(attrs, PyLong_FromUnsignedLong( 34 | (unsigned long)attr->filesize)); 35 | PyList_Append(attrs, PyLong_FromUnsignedLong( 36 | (unsigned long)attr->uid)); 37 | PyList_Append(attrs, PyLong_FromUnsignedLong( 38 | (unsigned long)attr->gid)); 39 | PyList_Append(attrs, PyLong_FromUnsignedLong( 40 | (unsigned long)attr->permissions)); 41 | PyList_Append(attrs, PyLong_FromUnsignedLong( 42 | (unsigned long)attr->atime)); 43 | PyList_Append(attrs, PyLong_FromUnsignedLong( 44 | (unsigned long)attr->mtime)); 45 | 46 | return attrs; 47 | } 48 | /* }}} */ 49 | 50 | /* {{{ PYLIBSSH2_Sftp_close 51 | */ 52 | static char PYLIBSSH2_Sftp_close_doc[] = "\n\ 53 | myfunction(name, value) -> returnType \n\ 54 | \n\ 55 | Arguments:\n\ 56 | \n\ 57 | Returns:\n\ 58 | "; 59 | 60 | static PyObject * 61 | PYLIBSSH2_Sftp_close(PYLIBSSH2_SFTP *self, PyObject *args) 62 | { 63 | int rc; 64 | PYLIBSSH2_SFTPHANDLE *handle; 65 | 66 | if (!PyArg_ParseTuple(args, "O:close", &handle)) { 67 | return NULL; 68 | } 69 | 70 | Py_BEGIN_ALLOW_THREADS 71 | rc = libssh2_sftp_close_handle(handle->sftphandle); 72 | Py_END_ALLOW_THREADS 73 | 74 | if (rc) { 75 | /* CLEAN: PYLIBSSH2_SFTPHANDLE_CANT_CLOSE_MSG */ 76 | PyErr_SetString(PYLIBSSH2_Error, "Unable to close sftp handle."); 77 | return NULL; 78 | } 79 | 80 | return Py_BuildValue("i", rc); 81 | } 82 | /* }}} */ 83 | 84 | /* {{{ PYLIBSSH2_Sftp_opendir 85 | */ 86 | static char PYLIBSSH2_Sftp_opendir_doc[] = "\n\ 87 | \n\ 88 | Arguments:\n\ 89 | \n\ 90 | Returns:\n\ 91 | "; 92 | 93 | static PyObject * 94 | PYLIBSSH2_Sftp_opendir(PYLIBSSH2_SFTP *self, PyObject *args) 95 | { 96 | LIBSSH2_SFTP_HANDLE *handle; 97 | char *path; 98 | 99 | if (!PyArg_ParseTuple(args, "s:opendir", &path)) { 100 | return NULL; 101 | } 102 | 103 | Py_BEGIN_ALLOW_THREADS 104 | handle = libssh2_sftp_opendir(self->sftp, path); 105 | Py_END_ALLOW_THREADS 106 | 107 | if (handle == NULL) { 108 | /* CLEAN: PYLIBSSH2_SFTPHANDLE_CANT_OPENDIR_MSG */ 109 | PyErr_SetString(PYLIBSSH2_Error, "Unable to open sftp directory."); 110 | return NULL; 111 | } 112 | 113 | return (PyObject *)PYLIBSSH2_Sftphandle_New(handle, 1); 114 | } 115 | /* }}} */ 116 | 117 | /* {{{ PYLIBSSH2_Sftp_readdir 118 | */ 119 | static char PYLIBSSH2_Sftp_readdir_doc[] = "\n\ 120 | \n\ 121 | Arguments:\n\ 122 | \n\ 123 | Returns:\n\ 124 | "; 125 | 126 | static PyObject * 127 | PYLIBSSH2_Sftp_readdir(PYLIBSSH2_SFTP *self, PyObject *args) 128 | { 129 | LIBSSH2_SFTP_ATTRIBUTES attrs; 130 | PYLIBSSH2_SFTPHANDLE *handle; 131 | int buffer_maxlen = 0; 132 | int longentry_maxlen = 255; 133 | PyObject *buffer; 134 | PyObject *list; 135 | 136 | if (!PyArg_ParseTuple(args, "O:readdir", &handle)) { 137 | return NULL; 138 | } 139 | 140 | buffer = PyString_FromStringAndSize(NULL, longentry_maxlen); 141 | if (buffer == NULL) { 142 | Py_INCREF(Py_None); 143 | return Py_None; 144 | } 145 | 146 | Py_BEGIN_ALLOW_THREADS 147 | buffer_maxlen = libssh2_sftp_readdir(handle->sftphandle, PyString_AsString(buffer), 148 | longentry_maxlen, &attrs); 149 | Py_END_ALLOW_THREADS 150 | 151 | if (buffer_maxlen == 0) { 152 | Py_INCREF(Py_None); 153 | return Py_None; 154 | } else if ( buffer_maxlen == -1) { 155 | /* CLEAN: PYLIBSSH2_SFTPHANDLE_CANT_READDIR_MSG */ 156 | PyErr_SetString(PYLIBSSH2_Error, "Unable to readdir."); 157 | return NULL; 158 | } 159 | 160 | if (buffer_maxlen != longentry_maxlen && 161 | _PyString_Resize(&buffer, buffer_maxlen) < 0) { 162 | Py_INCREF(Py_None); 163 | return Py_None; 164 | } 165 | 166 | list = PyList_New(0); 167 | PyList_Append(list, buffer); 168 | PyList_Append(list, get_attrs(&attrs)); 169 | 170 | return list; 171 | } 172 | /* }}} */ 173 | 174 | /* {{{ PYLIBSSH2_Sftp_listdir 175 | */ 176 | static char PYLIBSSH2_Sftp_listdir_doc[] = "\n\ 177 | \n\ 178 | Arguments:\n\ 179 | \n\ 180 | Returns:\n\ 181 | "; 182 | 183 | static PyObject * 184 | PYLIBSSH2_Sftp_listdir(PYLIBSSH2_SFTP *self, PyObject *args) 185 | { 186 | LIBSSH2_SFTP_ATTRIBUTES attrs; 187 | PYLIBSSH2_SFTPHANDLE *handle; 188 | int buffer_maxlen = 0; 189 | int longentry_maxlen = 255; 190 | PyObject *buffer; 191 | PyObject *all = NULL; 192 | PyObject *list = NULL; 193 | 194 | if (!PyArg_ParseTuple(args, "O:listdir", &handle)) { 195 | return NULL; 196 | } 197 | 198 | all = PyList_New(0); 199 | while (1) { 200 | buffer = PyString_FromStringAndSize(NULL, longentry_maxlen); 201 | if (buffer == NULL) { 202 | Py_INCREF(Py_None); 203 | return Py_None; 204 | } 205 | 206 | Py_BEGIN_ALLOW_THREADS 207 | buffer_maxlen = libssh2_sftp_readdir(handle->sftphandle, 208 | PyString_AsString(buffer), longentry_maxlen, &attrs); 209 | Py_END_ALLOW_THREADS 210 | 211 | if (buffer_maxlen == 0) { 212 | break; 213 | } else if (buffer_maxlen == -1) { 214 | PyErr_SetString(PYLIBSSH2_Error, "Unable to listdir."); 215 | return NULL; 216 | } 217 | 218 | if ( buffer_maxlen != longentry_maxlen && 219 | _PyString_Resize(&buffer, buffer_maxlen) < 0) { 220 | Py_INCREF(Py_None); 221 | return Py_None; 222 | } 223 | 224 | list = PyList_New(0); 225 | PyList_Append(list, buffer); 226 | PyList_Append(list, get_attrs(&attrs)); 227 | PyList_Append(all, list); 228 | } 229 | 230 | return all; 231 | } 232 | /* }}} */ 233 | 234 | /* {{{ PYLIBSSH2_Sftp_open 235 | */ 236 | static char PYLIBSSH2_Sftp_open_doc[] = "\n\ 237 | \n\ 238 | Arguments:\n\ 239 | \n\ 240 | Returns:\n\ 241 | "; 242 | 243 | static PyObject * 244 | PYLIBSSH2_Sftp_open(PYLIBSSH2_SFTP *self, PyObject *args) 245 | { 246 | LIBSSH2_SFTP_HANDLE *handle; 247 | char *path; 248 | char *flags = "r"; 249 | long mode = 0755; 250 | 251 | if (!PyArg_ParseTuple(args, "s|si:open", &path, &flags, &mode)) { 252 | return NULL; 253 | } 254 | 255 | Py_BEGIN_ALLOW_THREADS 256 | handle = libssh2_sftp_open(self->sftp, path, get_flags(flags), mode); 257 | Py_END_ALLOW_THREADS 258 | 259 | if (handle == NULL) { 260 | /* CLEAN: PYLIBSSH2_SFTP_CANT_OPEN_MSG */ 261 | PyErr_SetString(PYLIBSSH2_Error, "Unable to sftp open."); 262 | return NULL; 263 | } 264 | 265 | return (PyObject *)PYLIBSSH2_Sftphandle_New(handle, 1); 266 | 267 | } 268 | /* }}} */ 269 | 270 | /* {{{ PYLIBSSH2_Sftp_shutdown 271 | */ 272 | static char PYLIBSSH2_Sftp_shutdown_doc[] = "\n\ 273 | \n\ 274 | Arguments:\n\ 275 | \n\ 276 | Returns:\n\ 277 | "; 278 | 279 | static PyObject * 280 | PYLIBSSH2_Sftp_shutdown(PYLIBSSH2_SFTP *self, PyObject *args) 281 | { 282 | int rc; 283 | 284 | rc=libssh2_sftp_shutdown(self->sftp); 285 | 286 | if (rc == -1) { 287 | /* CLEAN: PYLIBSSH2_SFTP_CANT_SHUTDOWN_MSG */ 288 | PyErr_SetString(PYLIBSSH2_Error, "Unable to shutdown sftp."); 289 | return NULL; 290 | } 291 | 292 | return Py_BuildValue("i", rc); 293 | } 294 | /* }}} */ 295 | 296 | /* {{{ PYLIBSSH2_Sftp_read 297 | */ 298 | static char PYLIBSSH2_Sftp_read_doc[] = "\n\ 299 | \n\ 300 | Arguments:\n\ 301 | \n\ 302 | Returns:\n\ 303 | "; 304 | 305 | static PyObject * 306 | PYLIBSSH2_Sftp_read(PYLIBSSH2_SFTP *self, PyObject *args) 307 | { 308 | int rc; 309 | int buffer_maxlen; 310 | PyObject *buffer; 311 | PYLIBSSH2_SFTPHANDLE *handle; 312 | 313 | if (!PyArg_ParseTuple(args, "Oi:read", &handle, &buffer_maxlen)) { 314 | return NULL; 315 | } 316 | 317 | buffer = PyString_FromStringAndSize(NULL, buffer_maxlen); 318 | if (buffer == NULL) { 319 | Py_INCREF(Py_None); 320 | return Py_None; 321 | } 322 | 323 | Py_BEGIN_ALLOW_THREADS 324 | rc = libssh2_sftp_read(handle->sftphandle, PyString_AsString(buffer), 325 | buffer_maxlen); 326 | Py_END_ALLOW_THREADS 327 | 328 | if (rc > 0) { 329 | if ( rc != buffer_maxlen && _PyString_Resize(&buffer, rc) < 0) { 330 | Py_INCREF(Py_None); 331 | return Py_None; 332 | } 333 | return buffer; 334 | } 335 | 336 | Py_XDECREF(buffer); 337 | Py_INCREF(Py_None); 338 | 339 | return Py_None; 340 | } 341 | /* }}} */ 342 | 343 | /* {{{ PYLIBSSH2_Sftp_write 344 | */ 345 | static char PYLIBSSH2_Sftp_write_doc[] = "\n\ 346 | \n\ 347 | Arguments:\n\ 348 | \n\ 349 | Returns:\n\ 350 | "; 351 | 352 | static PyObject * 353 | PYLIBSSH2_Sftp_write(PYLIBSSH2_SFTP *self, PyObject *args) 354 | { 355 | int rc, buffer_len; 356 | char *buffer; 357 | PYLIBSSH2_SFTPHANDLE *handle; 358 | 359 | if (!PyArg_ParseTuple(args, "Os#:write", &handle, &buffer, &buffer_len)) { 360 | return NULL; 361 | } 362 | 363 | Py_BEGIN_ALLOW_THREADS 364 | rc = libssh2_sftp_write(handle->sftphandle, buffer, buffer_len); 365 | Py_END_ALLOW_THREADS 366 | 367 | if (rc < 0) { 368 | /* CLEAN: PYLIBSSH2_Sftp_CANT_WRITE_MSG */ 369 | PyErr_Format(PYLIBSSH2_Error, "Unable to write sftp."); 370 | return NULL; 371 | } 372 | 373 | return Py_BuildValue("i", rc); 374 | 375 | } 376 | /* }}} */ 377 | 378 | /* {{{ PYLIBSSH2_Sftp_tell 379 | */ 380 | static char PYLIBSSH2_Sftp_tell_doc[] = "\n\ 381 | \n\ 382 | Arguments:\n\ 383 | \n\ 384 | Returns:\n\ 385 | "; 386 | 387 | static PyObject * 388 | PYLIBSSH2_Sftp_tell(PYLIBSSH2_SFTP *self, PyObject *args) 389 | { 390 | PYLIBSSH2_SFTPHANDLE *handle; 391 | 392 | if (!PyArg_ParseTuple(args, "O:tell", &handle)) { 393 | return NULL; 394 | } 395 | 396 | return PyInt_FromLong(libssh2_sftp_tell(handle->sftphandle)); 397 | } 398 | /* }}} */ 399 | 400 | /* {{{ PYLIBSSH2_Sftp_seek 401 | */ 402 | static char PYLIBSSH2_Sftp_seek_doc[] = "\n\ 403 | \n\ 404 | Arguments:\n\ 405 | \n\ 406 | Returns:\n\ 407 | "; 408 | 409 | static PyObject * 410 | PYLIBSSH2_Sftp_seek(PYLIBSSH2_SFTP *self, PyObject *args) 411 | { 412 | PYLIBSSH2_SFTPHANDLE *handle; 413 | unsigned long offset=0; 414 | 415 | if (!PyArg_ParseTuple(args, "Ok:seek", &handle, &offset)) { 416 | return NULL; 417 | } 418 | 419 | Py_BEGIN_ALLOW_THREADS 420 | libssh2_sftp_seek(handle->sftphandle, offset); 421 | Py_END_ALLOW_THREADS 422 | 423 | return PyInt_FromLong(1); 424 | } 425 | /* }}} */ 426 | 427 | /* {{{ PYLIBSSH2_Sftp_unlink 428 | */ 429 | static char PYLIBSSH2_Sftp_unlink_doc[] = "\n\ 430 | \n\ 431 | Arguments:\n\ 432 | \n\ 433 | Returns:\n\ 434 | "; 435 | 436 | static PyObject * 437 | PYLIBSSH2_Sftp_unlink(PYLIBSSH2_SFTP *self, PyObject *args) 438 | { 439 | 440 | int rc; 441 | char *path; 442 | 443 | if (!PyArg_ParseTuple(args, "s:unlink", &path)) { 444 | return NULL; 445 | } 446 | 447 | Py_BEGIN_ALLOW_THREADS 448 | rc = libssh2_sftp_unlink(self->sftp, path); 449 | Py_END_ALLOW_THREADS 450 | 451 | return Py_BuildValue("i", rc); 452 | } 453 | /* }}} */ 454 | 455 | /* {{{ PYLIBSSH2_Sftp_rename 456 | */ 457 | static char PYLIBSSH2_Sftp_rename_doc[] = "\n\ 458 | \n\ 459 | Arguments:\n\ 460 | \n\ 461 | Returns:\n\ 462 | "; 463 | 464 | static PyObject * 465 | PYLIBSSH2_Sftp_rename(PYLIBSSH2_SFTP *self, PyObject *args) 466 | { 467 | int rc; 468 | char *src, *dst; 469 | 470 | if (!PyArg_ParseTuple(args, "ss:rename", &src, &dst)) { 471 | return NULL; 472 | } 473 | 474 | Py_BEGIN_ALLOW_THREADS 475 | rc = libssh2_sftp_rename(self->sftp, src, dst); 476 | Py_END_ALLOW_THREADS 477 | 478 | return Py_BuildValue("i", rc); 479 | } 480 | /* }}} */ 481 | 482 | /* {{{ PYLIBSSH2_Sftp_mkdir 483 | */ 484 | static char PYLIBSSH2_Sftp_mkdir_doc[] = "\n\ 485 | \n\ 486 | Arguments:\n\ 487 | \n\ 488 | Returns:\n\ 489 | "; 490 | 491 | static PyObject * 492 | PYLIBSSH2_Sftp_mkdir(PYLIBSSH2_SFTP *self, PyObject *args) 493 | { 494 | int rc; 495 | char *path; 496 | long mode = 0755; 497 | 498 | if (!PyArg_ParseTuple(args, "s|i:mkdir", &path, &mode)) { 499 | return NULL; 500 | } 501 | 502 | Py_BEGIN_ALLOW_THREADS 503 | rc = libssh2_sftp_mkdir(self->sftp, path, mode); 504 | Py_END_ALLOW_THREADS 505 | 506 | return Py_BuildValue("i", rc); 507 | } 508 | /* }}} */ 509 | 510 | /* {{{ PYLIBSSH2_Sftp_rmdir 511 | */ 512 | static char PYLIBSSH2_Sftp_rmdir_doc[] = "\n\ 513 | \n\ 514 | Arguments:\n\ 515 | \n\ 516 | Returns:\n\ 517 | "; 518 | 519 | static PyObject * 520 | PYLIBSSH2_Sftp_rmdir(PYLIBSSH2_SFTP *self, PyObject *args) 521 | { 522 | int rc; 523 | char *path; 524 | 525 | if (!PyArg_ParseTuple(args, "s:rmdir", &path)) { 526 | return NULL; 527 | } 528 | 529 | Py_BEGIN_ALLOW_THREADS 530 | rc = libssh2_sftp_rmdir(self->sftp, path); 531 | Py_END_ALLOW_THREADS 532 | 533 | return Py_BuildValue("i", rc); 534 | } 535 | /* }}} */ 536 | 537 | /* {{{ PYLIBSSH2_Sftp_realpath 538 | */ 539 | static char PYLIBSSH2_Sftp_realpath_doc[] = "\n\ 540 | \n\ 541 | Arguments:\n\ 542 | \n\ 543 | Returns:\n\ 544 | "; 545 | 546 | static PyObject * 547 | PYLIBSSH2_Sftp_realpath(PYLIBSSH2_SFTP *self, PyObject *args) 548 | { 549 | int rc, path_len = 0, target_len = 1024; 550 | int type = LIBSSH2_SFTP_REALPATH; 551 | char *path; 552 | PyObject *target; 553 | 554 | if (!PyArg_ParseTuple(args, "s#|i:realpath", &path, &path_len, &type)) { 555 | return NULL; 556 | } 557 | 558 | target = PyString_FromStringAndSize(NULL, target_len); 559 | if (target == NULL) { 560 | Py_INCREF(Py_None); 561 | return Py_None; 562 | } 563 | 564 | Py_BEGIN_ALLOW_THREADS 565 | rc = libssh2_sftp_symlink_ex(self->sftp, path, path_len, 566 | PyString_AsString(target), target_len, type); 567 | Py_END_ALLOW_THREADS 568 | 569 | if (rc > 0) { 570 | if (rc != target_len && _PyString_Resize(&target, rc) < 0) { 571 | Py_INCREF(Py_None); 572 | return Py_None; 573 | } 574 | return target; 575 | } 576 | 577 | Py_XDECREF(target); 578 | Py_INCREF(Py_None); 579 | 580 | return Py_None; 581 | } 582 | /* }}} */ 583 | 584 | /* {{{ PYLIBSSH2_Sftp_symlink 585 | */ 586 | static char PYLIBSSH2_Sftp_symlink_doc[] = "\n\ 587 | \n\ 588 | Arguments:\n\ 589 | \n\ 590 | Returns:\n\ 591 | "; 592 | 593 | static PyObject * 594 | PYLIBSSH2_Sftp_symlink(PYLIBSSH2_SFTP *self, PyObject *args) 595 | { 596 | int rc; 597 | char *path, *target; 598 | 599 | if (!PyArg_ParseTuple(args, "ss:symlink", &path, &target)) { 600 | return NULL; 601 | } 602 | 603 | Py_BEGIN_ALLOW_THREADS 604 | rc = libssh2_sftp_symlink(self->sftp, path, target); 605 | Py_END_ALLOW_THREADS 606 | 607 | if (rc == -1) { 608 | /* CLEAN: PYLIBSSH2_SFTP_CANT_SYMLINK_MSG */ 609 | PyErr_SetString(PYLIBSSH2_Error, "Unable to sftp symlink."); 610 | return NULL; 611 | } 612 | 613 | return Py_BuildValue("i", rc); 614 | } 615 | /* }}} */ 616 | 617 | /* {{{ PYLIBSSH2_Sftp_get_stat 618 | */ 619 | static char PYLIBSSH2_Sftp_get_stat_doc[] = "\n\ 620 | \n\ 621 | Arguments:\n\ 622 | \n\ 623 | Returns:\n\ 624 | "; 625 | 626 | static PyObject * 627 | PYLIBSSH2_Sftp_get_stat(PYLIBSSH2_SFTP *self, PyObject *args) 628 | { 629 | int rc; 630 | char *path; 631 | int path_len = 0; 632 | int type = LIBSSH2_SFTP_STAT; 633 | LIBSSH2_SFTP_ATTRIBUTES attr; 634 | 635 | if (!PyArg_ParseTuple(args, "s#|i:get_stat", &path, &path_len, &type)) { 636 | return NULL; 637 | } 638 | 639 | Py_BEGIN_ALLOW_THREADS 640 | rc = libssh2_sftp_stat_ex(self->sftp, path, path_len, type, &attr); 641 | Py_END_ALLOW_THREADS 642 | 643 | if (rc == -1) { 644 | /* CLEAN: PYLIBSSH2_SFTP_CANT_GETSTAT_MSG */ 645 | PyErr_SetString(PYLIBSSH2_Error, "Unable to get stat."); 646 | return NULL; 647 | } 648 | 649 | return get_attrs(&attr); 650 | } 651 | /* }}} */ 652 | 653 | /* {{{ PYLIBSSH2_Sftp_set_stat 654 | */ 655 | static char PYLIBSSH2_Sftp_set_stat_doc[] = "\n\ 656 | \n\ 657 | Arguments:\n\ 658 | \n\ 659 | Returns:\n\ 660 | "; 661 | 662 | static PyObject * 663 | PYLIBSSH2_Sftp_set_stat(PYLIBSSH2_SFTP *self, PyObject *args) 664 | { 665 | int rc; 666 | char *path; 667 | LIBSSH2_SFTP_ATTRIBUTES attr; 668 | PyObject *attrs; 669 | 670 | if (!PyArg_ParseTuple(args, "sO:set_stat", &path, &attrs)) { 671 | return NULL; 672 | } 673 | 674 | attr.flags = 0; 675 | if (PyMapping_HasKeyString(attrs, "perms")) { 676 | attr.flags |= LIBSSH2_SFTP_ATTR_PERMISSIONS; 677 | attr.permissions = PyLong_AsLong(PyDict_GetItemString(attrs, "perms")); 678 | } 679 | 680 | if (PyMapping_HasKeyString(attrs, "uid") && 681 | PyMapping_HasKeyString(attrs, "gid")) { 682 | if (PyMapping_HasKeyString(attrs, "uid")) { 683 | attr.flags |= LIBSSH2_SFTP_ATTR_UIDGID; 684 | attr.uid = PyLong_AsLong(PyDict_GetItemString(attrs,"uid")); 685 | } 686 | if (PyMapping_HasKeyString(attrs, "gid")) { 687 | attr.flags |= LIBSSH2_SFTP_ATTR_UIDGID; 688 | attr.uid = PyLong_AsLong(PyDict_GetItemString(attrs,"gid")); 689 | } 690 | } 691 | 692 | if (PyMapping_HasKeyString(attrs, "atime") && 693 | PyMapping_HasKeyString(attrs, "mtime")) { 694 | if (PyMapping_HasKeyString(attrs, "atime")) { 695 | attr.flags |= LIBSSH2_SFTP_ATTR_ACMODTIME; 696 | attr.uid = PyLong_AsLong(PyDict_GetItemString(attrs,"atime")); 697 | } 698 | if (PyMapping_HasKeyString(attrs, "mtime")) { 699 | attr.flags |= LIBSSH2_SFTP_ATTR_ACMODTIME; 700 | attr.uid = PyLong_AsLong(PyDict_GetItemString(attrs,"mtime")); 701 | } 702 | } 703 | 704 | Py_BEGIN_ALLOW_THREADS 705 | rc = libssh2_sftp_setstat(self->sftp, path, &attr); 706 | Py_END_ALLOW_THREADS 707 | 708 | if (rc == -1) { 709 | PyErr_SetString(PYLIBSSH2_Error, "Unable to stat."); 710 | return NULL; 711 | } 712 | 713 | return Py_BuildValue("i", rc); 714 | } 715 | /* }}} */ 716 | 717 | /* {{{ PYLIBSSH2_Sftp_methods[] 718 | * 719 | * ADD_METHOD(name) expands to a correct PyMethodDef declaration 720 | * { 'name', (PyCFunction)PYLIBSSH2_Sftp_name, METH_VARARGS } 721 | * for convenience 722 | */ 723 | #define ADD_METHOD(name) \ 724 | { #name, (PyCFunction)PYLIBSSH2_Sftp_##name, METH_VARARGS, PYLIBSSH2_Sftp_##name##_doc } 725 | 726 | static PyMethodDef PYLIBSSH2_Sftp_methods[] = 727 | { 728 | ADD_METHOD(close), 729 | ADD_METHOD(opendir), 730 | ADD_METHOD(readdir), 731 | ADD_METHOD(listdir), 732 | ADD_METHOD(open), 733 | ADD_METHOD(shutdown), 734 | ADD_METHOD(read), 735 | ADD_METHOD(write), 736 | ADD_METHOD(tell), 737 | ADD_METHOD(seek), 738 | ADD_METHOD(unlink), 739 | ADD_METHOD(rename), 740 | ADD_METHOD(mkdir), 741 | ADD_METHOD(rmdir), 742 | ADD_METHOD(realpath), 743 | ADD_METHOD(symlink), 744 | ADD_METHOD(get_stat), 745 | ADD_METHOD(set_stat), 746 | { NULL, NULL } 747 | }; 748 | #undef ADD_METHOD 749 | /* }}} */ 750 | 751 | 752 | /* {{{ PYLIBSSH2_Sftp_New 753 | */ 754 | PYLIBSSH2_SFTP * 755 | PYLIBSSH2_Sftp_New(LIBSSH2_SFTP *sftp, int dealloc) 756 | { 757 | PYLIBSSH2_SFTP *self; 758 | 759 | self = PyObject_New(PYLIBSSH2_SFTP, &PYLIBSSH2_Sftp_Type); 760 | if (self == NULL) { 761 | return NULL; 762 | } 763 | 764 | self->sftp = sftp; 765 | self->dealloc = dealloc; 766 | 767 | return self; 768 | } 769 | /* }}} */ 770 | 771 | /* {{{ PYLIBSSH2_Sftp_dealloc 772 | */ 773 | static void 774 | PYLIBSSH2_Sftp_dealloc(PYLIBSSH2_SFTP *self) 775 | { 776 | PyObject_Del(self); 777 | } 778 | /* }}} */ 779 | 780 | /* {{{ PYLIBSSH2_Sftp_getattr 781 | */ 782 | static PyObject * 783 | PYLIBSSH2_Sftp_getattr(PYLIBSSH2_SFTP *self, char *name) 784 | { 785 | return Py_FindMethod(PYLIBSSH2_Sftp_methods, (PyObject *)self, name); 786 | } 787 | /* }}} */ 788 | 789 | /* {{{ PYLIBSSH2_Sftp_Type 790 | * 791 | * see /usr/include/python2.5/object.h line 261 792 | */ 793 | PyTypeObject PYLIBSSH2_Sftp_Type = { 794 | PyObject_HEAD_INIT(NULL) 795 | 0, /* ob_size */ 796 | "Sftp", /* tp_name */ 797 | sizeof(PYLIBSSH2_SFTP), /* tp_basicsize */ 798 | 0, /* tp_itemsize */ 799 | (destructor)PYLIBSSH2_Sftp_dealloc, /* tp_dealloc */ 800 | 0, /* tp_print */ 801 | (getattrfunc)PYLIBSSH2_Sftp_getattr, /* tp_getattr */ 802 | 0, /* tp_setattr */ 803 | 0, /* tp_compare */ 804 | 0, /* tp_repr */ 805 | 0, /* tp_as_number */ 806 | 0, /* tp_as_sequence */ 807 | 0, /* tp_as_mapping */ 808 | 0, /* tp_hash */ 809 | 0, /* tp_call */ 810 | 0, /* tp_str */ 811 | 0, /* tp_getattro */ 812 | 0, /* tp_setattro */ 813 | 0, /* tp_as_buffer */ 814 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 815 | "Sftp objects", /* tp_doc */ 816 | }; 817 | /* }}} */ 818 | 819 | /* {{{ init_libssh2_Sftp 820 | */ 821 | int 822 | init_libssh2_Sftp(PyObject *dict) 823 | { 824 | PYLIBSSH2_Sftp_Type.ob_type = &PyType_Type; 825 | Py_XINCREF(&PYLIBSSH2_Sftp_Type); 826 | PyDict_SetItemString(dict, "SFTPType", (PyObject *) &PYLIBSSH2_Sftp_Type); 827 | 828 | return 1; 829 | } 830 | /* }}} */ 831 | -------------------------------------------------------------------------------- /src/sftp.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_SFTP_H_ 22 | #define _PYLIBSSH2_SFTP_H_ 23 | 24 | #include 25 | #include 26 | 27 | extern int init_libssh2_Sftp(PyObject *); 28 | 29 | extern PyTypeObject PYLIBSSH2_Sftp_Type; 30 | 31 | #define PYLIBSSH2_Sftp_Check(v) ((v)->ob_type == &PYLIBSSH2_Sftp_Type) 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | LIBSSH2_SFTP *sftp; 36 | int dealloc; 37 | } PYLIBSSH2_SFTP; 38 | 39 | #endif /* _PYLIBSSH2_SFTP_H_ */ 40 | -------------------------------------------------------------------------------- /src/sftphandle.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include 22 | #define PYLIBSSH2_MODULE 23 | #include "pylibssh2.h" 24 | 25 | /* 26 | * ADD_METHOD(name) expands to a correct PyMethodDef declaration 27 | * { 'name', (PyCFunction)PYLIBSSH2_Sftphandle_name, METH_VARARGS } 28 | * for convenience 29 | */ 30 | #define ADD_METHOD(name) \ 31 | { #name, (PyCFunction)PYLIBSSH2_Sftphandle_##name, METH_VARARGS, PYLIBSSH2_Sftphandle_##name##_doc } 32 | 33 | static PyMethodDef PYLIBSSH2_Sftphandle_methods[] = 34 | { 35 | { NULL, NULL } 36 | }; 37 | 38 | PYLIBSSH2_SFTPHANDLE * 39 | PYLIBSSH2_Sftphandle_New(LIBSSH2_SFTP_HANDLE *sftphandle, int dealloc) 40 | { 41 | PYLIBSSH2_SFTPHANDLE *self; 42 | 43 | self = PyObject_New(PYLIBSSH2_SFTPHANDLE, &PYLIBSSH2_Sftphandle_Type); 44 | if (self == NULL) { 45 | return NULL; 46 | } 47 | 48 | self->sftphandle = sftphandle; 49 | self->dealloc = dealloc; 50 | 51 | return self; 52 | } 53 | 54 | static void 55 | PYLIBSSH2_Sftphandle_dealloc(PYLIBSSH2_SFTPHANDLE *self) 56 | { 57 | PyObject_Del(self); 58 | } 59 | 60 | static PyObject * 61 | PYLIBSSH2_Sftphandle_getattr(PYLIBSSH2_SFTPHANDLE *self, char *name) 62 | { 63 | return Py_FindMethod(PYLIBSSH2_Sftphandle_methods, (PyObject *)self, name); 64 | } 65 | 66 | /* 67 | * see /usr/include/python2.5/object.c line 261 68 | */ 69 | PyTypeObject PYLIBSSH2_Sftphandle_Type = { 70 | PyObject_HEAD_INIT(NULL) 71 | 0, /* ob_size */ 72 | "Sftphandle", /* tp_name */ 73 | sizeof(PYLIBSSH2_SFTPHANDLE), /* tp_basicsize */ 74 | 0, /* tp_itemsize */ 75 | (destructor)PYLIBSSH2_Sftphandle_dealloc, /* tp_dealloc */ 76 | 0, /* tp_print */ 77 | (getattrfunc)PYLIBSSH2_Sftphandle_getattr, /* tp_getattr */ 78 | 0, /* tp_setattr */ 79 | 0, /* tp_compare */ 80 | 0, /* tp_repr */ 81 | 0, /* tp_as_number */ 82 | 0, /* tp_as_sequence */ 83 | 0, /* tp_as_mapping */ 84 | 0, /* tp_hash */ 85 | 0, /* tp_call */ 86 | 0, /* tp_str */ 87 | 0, /* tp_getattro */ 88 | 0, /* tp_setattro */ 89 | 0, /* tp_as_buffer */ 90 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 91 | "Sftphandle objects", /* tp_doc */ 92 | }; 93 | 94 | int 95 | init_libssh2_Sftphandle(PyObject *dict) 96 | { 97 | PYLIBSSH2_Sftphandle_Type.ob_type = &PyType_Type; 98 | Py_XINCREF(&PYLIBSSH2_Sftphandle_Type); 99 | PyDict_SetItemString(dict, "SftphandleType", (PyObject *)&PYLIBSSH2_Sftphandle_Type); 100 | 101 | return 1; 102 | } 103 | -------------------------------------------------------------------------------- /src/sftphandle.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_SFTPHANDLE_H_ 22 | #define _PYLIBSSH2_SFTPHANDLE_H_ 23 | 24 | #include 25 | #include 26 | 27 | extern int init_libssh2_Sftphandle(PyObject *); 28 | 29 | extern PyTypeObject PYLIBSSH2_Sftphandle_Type; 30 | 31 | #define PYLIBSSH2_Sftphandle_Check(v) ((v)->ob_type == &PYLIBSSH2_Sftphandle_Type) 32 | 33 | typedef struct { 34 | PyObject_HEAD 35 | LIBSSH2_SFTP_HANDLE *sftphandle; 36 | int dealloc; 37 | } PYLIBSSH2_SFTPHANDLE; 38 | 39 | PYLIBSSH2_SFTPHANDLE * PYLIBSSH2_Sftphandle_New(LIBSSH2_SFTP_HANDLE *, int); 40 | 41 | #endif /* _PYLIBSSH2_SFTPHANDLE_H_ */ 42 | -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #include "util.h" 22 | 23 | /* {{{ get_flags 24 | */ 25 | unsigned long 26 | get_flags(char *mode) { 27 | int i=0; 28 | unsigned long f=0; 29 | 30 | struct { 31 | char mode; 32 | unsigned long flags; 33 | } modeflags[5] = { 34 | {'a', LIBSSH2_FXF_APPEND }, 35 | {'w', LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT }, 36 | {'r', LIBSSH2_FXF_READ }, 37 | {'+', LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE }, 38 | {'x', LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_EXCL | LIBSSH2_FXF_CREAT } 39 | }; 40 | 41 | for(i=0; i<5; i++) { 42 | if(strchr(mode, modeflags[i].mode)) { 43 | f |= modeflags[i].flags; 44 | } 45 | } 46 | 47 | return f; 48 | } 49 | /* }}} */ 50 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * pylibssh2 - python bindings for libssh2 library 3 | * 4 | * Copyright (C) 2005 Keyphrene.com. 5 | * Copyright (C) 2010 Wallix Inc. 6 | * 7 | * This library is free software; you can redistribute it and/or modify it 8 | * under the terms of the GNU Lesser General Public License as published by the 9 | * Free Software Foundation; either version 2.1 of the License, or (at your 10 | * option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, but WITHOUT 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 15 | * details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this library; if not, write to the Free Software Foundation, Inc., 19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | #ifndef _PYLIBSSH2_UTIL_H_ 22 | #define _PYLIBSSH2_UTIL_H_ 23 | 24 | #include 25 | #include 26 | 27 | /* 28 | * Retrieve files attribute for sftp connection. 29 | */ 30 | unsigned long get_flags(char *mode); 31 | 32 | #endif /* _PYLIBSSH2_UTIL_H_ */ 33 | -------------------------------------------------------------------------------- /tests/test_session.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2011 WALLIX, SAS. All rights reserved. 3 | # Licensed computer software. Property of WALLIX. 4 | # Product Name: pylibssh2 5 | # Author(s) : Sofian Brabez 6 | # Id: $Id: test_session.py 145 2011-01-11 11:12:38Z sbrabez $ 7 | # URL: $URL: svn+ssh://ohervieu@zoo.ifr.lan/srv/svn/pylibssh2/trunk/tests/test_session.py $ 8 | # Module description: 9 | # Compile with: 10 | # 11 | """ 12 | Unit tests for Session 13 | """ 14 | 15 | import socket 16 | import unittest 17 | 18 | class SessionTest(unittest.TestCase): 19 | def setUp(self): 20 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 21 | self.socket.connect(("127.0.0.1", 22)) 22 | 23 | def test_import(self): 24 | ok = False 25 | try: 26 | import libssh2 # pyflakes:ignore 27 | ok=True 28 | except ImportError: 29 | ok=False 30 | 31 | self.assertTrue(ok) 32 | 33 | def test_session_create(self): 34 | import libssh2 35 | session = libssh2.Session() 36 | self.assertTrue(isinstance(session, libssh2.session.Session)) 37 | 38 | def test_session_startup(self): 39 | import libssh2 40 | session = libssh2.Session() 41 | session.startup(self.socket) 42 | self.assertEqual(session.userauth_authenticated(), 0) 43 | 44 | def tearDown(self): 45 | self.socket.close() 46 | 47 | if __name__ == '__main__': 48 | unittest.main() 49 | --------------------------------------------------------------------------------