5772772 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11-win32/libssh]$ cat -n client.c
  1 /* client.c file */
  2 /*
  3 Copyright 2003 Aris Adamantiadis
  4 
  5 This file is part of the SSH Library
  6 
  7 The SSH Library is free software; you can redistribute it and/or modify
  8 it under the terms of the GNU Lesser General Public License as published by
  9 the Free Software Foundation; either version 2.1 of the License, or (at your
 10 option) any later version.
 11 
 12 The SSH Library is distributed in the hope that it will be useful, but
 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 14 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 15 License for more details.
 16 
 17 You should have received a copy of the GNU Lesser General Public License
 18 along with the SSH Library; see the file COPYING.  If not, write to
 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 20 MA 02111-1307, USA. */
 21 
 22 #include "libssh/priv.h"
 23 #include <stdio.h>
 24 #include <unistd.h>
 25 #include <stdlib.h>
 26 #include <string.h>
 27 #ifdef HAVE_NETDB_H
 28 #include <netdb.h>
 29 #endif
 30 #ifdef HAVE_WINDOWS_H
 31 #include <windows.h>
 32 #endif
 33 #ifdef HAVE_SYS_TYPES_H
 34 #include <sys/types.h>
 35 #endif
 36 #ifdef HAVE_SYS_SOCKET_H
 37 #include <sys/socket.h>
 38 #endif
 39 #include "libssh/ssh2.h"
 40 static void ssh_cleanup(SSH_SESSION *session);
 41 #define set_status(opt,status) do {\
 42         if (opt->connect_status_function) \
 43             opt->connect_status_function(opt->connect_status_arg, status); \
 44     } while (0)
 45 /* simply gets a banner from a socket */
 46 
 47 char *ssh_get_banner(SSH_SESSION *session){
 48     char buffer[128];
 49     int i = 0;
 50     ssize_t read_ret;
 51 
 52     while (i < 127) {
 53         if((read_ret = recv(session->fd, &buffer[i], 1, 0))<=0){
 54             ssh_set_error(session,SSH_CONNECTION_LOST,"Remote host closed connection");
 55             return NULL;
 56         }
 57         if (buffer[i] == '\015')
 58             buffer[i] = 0;
 59         if (buffer[i] == '\012') {
 60             buffer[i] = 0;
 61             return strdup(buffer);
 62         }
 63     i++;
 64     }
 65     ssh_set_error(NULL,SSH_FATAL,"Too large banner");
 66     return NULL;
 67 }
 68 
 69 /* ssh_send_banner sends a SSH banner to the server */
 70 /* TODO select a banner compatible with server version */
 71 /* switch SSH1/1.5/2 */
 72 /* and quit when the server is SSH1 only */
 73 
 74 void ssh_send_banner(SSH_SESSION *session){
 75     char *banner=CLIENTBANNER ;
 76     char buffer[128];
 77     if(session->options->clientbanner)
 78         banner=session->options->clientbanner;
 79     session->clientbanner=strdup(banner);
 80     snprintf(buffer,128,"%s\r\n",session->clientbanner);
 81     send(session->fd,buffer,strlen(buffer),0);
 82 }
 83 
 84 
 85 int dh_handshake(SSH_SESSION *session){
 86     STRING *e,*f,*pubkey,*signature;
 87     packet_clear_out(session);
 88     buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_INIT);
 89     dh_generate_x(session);
 90     dh_generate_e(session);
 91     e=dh_get_e(session);
 92     buffer_add_ssh_string(session->out_buffer,e);
 93     packet_send(session);
 94     free(e);
 95     if(packet_wait(session,SSH2_MSG_KEXDH_REPLY,1))
 96         return -1;
 97     pubkey=buffer_get_ssh_string(session->in_buffer);
 98     if(!pubkey){
 99         ssh_set_error(NULL,SSH_FATAL,"No public key in packet");
100         return -1;
101     }
102     dh_import_pubkey(session,pubkey);
103     f=buffer_get_ssh_string(session->in_buffer);
104     if(!f){
105         ssh_set_error(NULL,SSH_FATAL,"No F number in packet");
106         return -1;
107     }
108     dh_import_f(session,f);
109     free(f);
110     if(!(signature=buffer_get_ssh_string(session->in_buffer))){
111         ssh_set_error(NULL,SSH_FATAL,"No signature in packet");
112         return -1;
113     }
114 
115     dh_build_k(session);
116     packet_wait(session,SSH2_MSG_NEWKEYS,1);
117     ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
118     packet_clear_out(session);
119     buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
120     packet_send(session);
121     ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
122     make_sessionid(session);
123     /* set the cryptographic functions for the next crypto (it is needed for generate_session_keys for key lenghts) */
124     if(crypt_set_algorithms(session))
125         return -1;
126     generate_session_keys(session);
127     /* verify the host's signature. XXX do it sooner */
128     if(signature_verify(session,signature)){
129         free(signature);
130         return -1;
131     }
132     free(signature);    /* forget it for now ... */
133     /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
134     if(session->current_crypto)
135         crypto_free(session->current_crypto);
136     /* XXX later, include a function to change keys */
137     session->current_crypto=session->next_crypto;
138     session->next_crypto=crypto_new();
139     return 0;
140 }
141 
142 int ssh_service_request(SSH_SESSION *session,char *service){
143     STRING *service_s;
144     packet_clear_out(session);
145     buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_REQUEST);
146     service_s=string_from_char(service);
147     buffer_add_ssh_string(session->out_buffer,service_s);
148     free(service_s);
149     packet_send(session);
150     ssh_say(3,"Sent SSH_MSG_SERVICE_REQUEST (service %s)\n",service);
151     if(packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1)){
152         ssh_set_error(session,SSH_INVALID_DATA,"did not receive SERVICE_ACCEPT");
153         return -1;
154     }
155     ssh_say(3,"Received SSH_MSG_SERVICE_ACCEPT (service %s)\n",service);
156     return 0;
157 }
158 
159 SSH_SESSION *ssh_connect(SSH_OPTIONS *options){
160   SSH_SESSION *session;
161   int fd;
162   if(!options){
163       ssh_set_error(NULL,SSH_FATAL,"Null argument given to ssh_connect !");
164       return NULL;
165   }
166   ssh_crypto_init();
167   if(options->fd==-1 && !options->host){
168       ssh_set_error(NULL,SSH_FATAL,"Hostname required");
169       return NULL;
170   } 
171   if(options->fd != -1)
172       fd=options->fd;
173   else
174       fd=ssh_connect_host(options->host,options->bindaddr,options->port,
175           options->timeout,options->timeout_usec);    
176   if(fd<0) {
177       ssh_set_error(NULL,SSH_FATAL,"ssh_connect_host failed");
178       return NULL;
179   }
180   set_status(options,0.2);
181   session=ssh_session_new();
182   session->fd=fd;
183   session->alive=1;
184       session->options=options;
185   if(!(session->serverbanner=ssh_get_banner(session))){
186       ssh_cleanup(session);
187       ssh_set_error(NULL,SSH_FATAL,"ssh_get_banner failed");
188       return NULL;
189   }
190   set_status(options,0.4);
191   ssh_say(2,"banner : %s\n",session->serverbanner);
192   ssh_send_banner(session);
193   set_status(options,0.5);
194   if(ssh_get_kex(session,0)){
195       ssh_disconnect(session);
196       ssh_set_error(NULL,SSH_FATAL,"ssh_get_kex failed");
197       return NULL;
198   }
199   set_status(options,0.6);
200   list_kex(&session->server_kex);
201   if(set_kex(session)){
202       ssh_disconnect(session);
203       ssh_set_error(NULL,SSH_FATAL,"set_kex failed");
204       return NULL;
205   }
206   send_kex(session,0);
207   set_status(options,0.8);
208   if(dh_handshake(session)){
209       ssh_disconnect(session);
210       ssh_set_error(NULL,SSH_FATAL,"dh_handshake failed");
211       return NULL;
212   }
213   set_status(options,1.0);
214   session->connected=1;
215   return session;
216 }
217 
218 static void ssh_cleanup(SSH_SESSION *session){
219     int i;
220     if(session->serverbanner)
221         free(session->serverbanner);
222     if(session->clientbanner)
223         free(session->clientbanner);
224     if(session->in_buffer)
225         buffer_free(session->in_buffer);
226     if(session->out_buffer)
227         buffer_free(session->out_buffer);
228     if(session->banner)
229         free(session->banner);
230     if(session->options)
231         options_free(session->options);
232     if(session->current_crypto)
233         crypto_free(session->current_crypto);
234     if(session->next_crypto)
235         crypto_free(session->next_crypto);
236 
237     // delete all channels
238     while(session->channels)
239         channel_free(session->channels);
240     if(session->client_kex.methods)
241         for(i=0;i<10;i++)
242             if(session->client_kex.methods[i])
243                 free(session->client_kex.methods[i]);
244     if(session->server_kex.methods)
245         for(i=0;i<10;++i)
246             if(session->server_kex.methods[i])
247                 free(session->server_kex.methods[i]);
248     free(session->client_kex.methods);
249     free(session->server_kex.methods);
250     memset(session,'X',sizeof(SSH_SESSION)); /* burn connection, it could hangs sensitive datas */
251     free(session);
252 }
253 
254 char *ssh_get_issue_banner(SSH_SESSION *session){
255     if(!session->banner)
256         return NULL;
257     return string_to_char(session->banner);
258 }
259 
260 void ssh_disconnect(SSH_SESSION *session){
261     STRING *str;
262     if(session->fd!= -1) {
263         packet_clear_out(session);
264         buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT);
265         buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION));
266         str=string_from_char("Bye Bye");
267         buffer_add_ssh_string(session->out_buffer,str);
268         free(str);
269         packet_send(session);
270         close(session->fd);
271         session->fd=-1;
272     }
273     session->alive=0;
274     ssh_cleanup(session);
275 }
276 
277 const char *ssh_copyright(){
278     return LIBSSH_VERSION " (c) 2003-2004 Aris Adamantiadis (aris@0xbadc0de.be)"
279                 " Distributed under the LGPL, please refer to COPYING file for informations"
280                 " about your rights" ;
281 }
5772773 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11-win32/libssh]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2007-02-17 17:46:50