5772779 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11/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 <stdio.h>
 23 #include <unistd.h>
 24 #include <stdlib.h>
 25 #include <string.h>
 26 #include <netdb.h>
 27 #include "libssh/priv.h"
 28 #include "libssh/ssh2.h"
 29 static void ssh_cleanup(SSH_SESSION *session);
 30 #define set_status(opt,status) do {\
 31         if (opt->connect_status_function) \
 32             opt->connect_status_function(opt->connect_status_arg, status); \
 33     } while (0)
 34 /* simply gets a banner from a socket */
 35 char *ssh_get_banner(SSH_SESSION *session){
 36     char buffer[128];
 37     int i = 0;
 38     while (i < 127) {
 39         if(read(session->fd, &buffer[i], 1)<=0){
 40             ssh_set_error(session,SSH_CONNECTION_LOST,"Remote host closed connection");
 41             return NULL;
 42         }
 43         if (buffer[i] == '\r')
 44             buffer[i] = 0;
 45         if (buffer[i] == '\n') {
 46             buffer[i] = 0;
 47             return strdup(buffer);
 48         }
 49     i++;
 50     }
 51     ssh_set_error(NULL,SSH_FATAL,"Too large banner");
 52     return NULL;
 53 }
 54 
 55 /* ssh_send_banner sends a SSH banner to the server */
 56 /* TODO select a banner compatible with server version */
 57 /* switch SSH1/1.5/2 */
 58 /* and quit when the server is SSH1 only */
 59 
 60 void ssh_send_banner(SSH_SESSION *session){
 61     char *banner=CLIENTBANNER ;
 62     char buffer[128];
 63     if(session->options->clientbanner)
 64         banner=session->options->clientbanner;
 65     session->clientbanner=strdup(banner);
 66     snprintf(buffer,128,"%s\r\n",session->clientbanner);
 67     write(session->fd,buffer,strlen(buffer));
 68 }
 69 
 70 
 71 int dh_handshake(SSH_SESSION *session){
 72     STRING *e,*f,*pubkey,*signature;
 73     packet_clear_out(session);
 74     buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_INIT);
 75     dh_generate_x(session);
 76     dh_generate_e(session);
 77     e=dh_get_e(session);
 78     buffer_add_ssh_string(session->out_buffer,e);
 79     packet_send(session);
 80     free(e);
 81     if(packet_wait(session,SSH2_MSG_KEXDH_REPLY,1))
 82         return -1;
 83     pubkey=buffer_get_ssh_string(session->in_buffer);
 84     if(!pubkey){
 85         ssh_set_error(NULL,SSH_FATAL,"No public key in packet");
 86         return -1;
 87     }
 88     dh_import_pubkey(session,pubkey);
 89     f=buffer_get_ssh_string(session->in_buffer);
 90     if(!f){
 91         ssh_set_error(NULL,SSH_FATAL,"No F number in packet");
 92         return -1;
 93     }
 94     dh_import_f(session,f);
 95     free(f);
 96     if(!(signature=buffer_get_ssh_string(session->in_buffer))){
 97         ssh_set_error(NULL,SSH_FATAL,"No signature in packet");
 98         return -1;
 99     }
100 
101     dh_build_k(session);
102     packet_wait(session,SSH2_MSG_NEWKEYS,1);
103     ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
104     packet_clear_out(session);
105     buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
106     packet_send(session);
107     ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
108     make_sessionid(session);
109     /* set the cryptographic functions for the next crypto (it is needed for generate_session_keys for key lenghts) */
110     if(crypt_set_algorithms(session))
111         return -1;
112     generate_session_keys(session);
113     /* verify the host's signature. XXX do it sooner */
114     if(signature_verify(session,signature)){
115         free(signature);
116         return -1;
117     }
118     free(signature);    /* forget it for now ... */
119     /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
120     if(session->current_crypto)
121         crypto_free(session->current_crypto);
122     /* XXX later, include a function to change keys */
123     session->current_crypto=session->next_crypto;
124     session->next_crypto=crypto_new();
125     return 0;
126 }
127 
128 int ssh_service_request(SSH_SESSION *session,char *service){
129     STRING *service_s;
130     packet_clear_out(session);
131     buffer_add_u8(session->out_buffer,SSH2_MSG_SERVICE_REQUEST);
132     service_s=string_from_char(service);
133     buffer_add_ssh_string(session->out_buffer,service_s);
134     free(service_s);
135     packet_send(session);
136     ssh_say(3,"Sent SSH_MSG_SERVICE_REQUEST (service %s)\n",service);
137     if(packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1)){
138         ssh_set_error(session,SSH_INVALID_DATA,"did not receive SERVICE_ACCEPT");
139         return -1;
140     }
141     ssh_say(3,"Received SSH_MSG_SERVICE_ACCEPT (service %s)\n",service);
142     return 0;
143 }
144 
145 SSH_SESSION *ssh_connect(SSH_OPTIONS *options){
146   SSH_SESSION *session;
147   int fd;
148   if(!options){
149       ssh_set_error(NULL,SSH_FATAL,"Null argument given to ssh_connect !");
150       return NULL;
151   }
152   ssh_crypto_init();
153   if(options->fd==-1 && !options->host){
154       ssh_set_error(NULL,SSH_FATAL,"Hostname required");
155       return NULL;
156   } 
157   if(options->fd != -1)
158       fd=options->fd;
159   else
160       fd=ssh_connect_host(options->host,options->bindaddr,options->port,
161           options->timeout,options->timeout_usec);    
162   if(fd<0)
163       return NULL;
164   set_status(options,0.2);
165   session=ssh_session_new();
166   session->fd=fd;
167   session->alive=1;
168       session->options=options;
169   if(!(session->serverbanner=ssh_get_banner(session))){
170       ssh_cleanup(session);
171       return NULL;
172   }
173   set_status(options,0.4);
174   ssh_say(2,"banner : %s\n",session->serverbanner);
175   ssh_send_banner(session);
176   set_status(options,0.5);
177   if(ssh_get_kex(session,0)){
178       ssh_disconnect(session);
179       return NULL;
180   }
181   set_status(options,0.6);
182   list_kex(&session->server_kex);
183   if(set_kex(session)){
184       ssh_disconnect(session);
185       return NULL;
186   }
187   send_kex(session,0);
188   set_status(options,0.8);
189   if(dh_handshake(session)){
190       ssh_disconnect(session);
191       return NULL;
192   }
193   set_status(options,1.0);
194   session->connected=1;
195   return session;
196 }
197 
198 static void ssh_cleanup(SSH_SESSION *session){
199     int i;
200     if(session->serverbanner)
201         free(session->serverbanner);
202     if(session->clientbanner)
203         free(session->clientbanner);
204     if(session->in_buffer)
205         buffer_free(session->in_buffer);
206     if(session->out_buffer)
207         buffer_free(session->out_buffer);
208     if(session->banner)
209         free(session->banner);
210     if(session->options)
211         options_free(session->options);
212     if(session->current_crypto)
213         crypto_free(session->current_crypto);
214     if(session->next_crypto)
215         crypto_free(session->next_crypto);
216 
217     // delete all channels
218     while(session->channels)
219         channel_free(session->channels);
220     if(session->client_kex.methods)
221         for(i=0;i<10;i++)
222             if(session->client_kex.methods[i])
223                 free(session->client_kex.methods[i]);
224     if(session->server_kex.methods)
225         for(i=0;i<10;++i)
226             if(session->server_kex.methods[i])
227                 free(session->server_kex.methods[i]);
228     free(session->client_kex.methods);
229     free(session->server_kex.methods);
230     memset(session,'X',sizeof(SSH_SESSION)); /* burn connection, it could hangs sensitive datas */
231     free(session);
232 }
233 
234 char *ssh_get_issue_banner(SSH_SESSION *session){
235     if(!session->banner)
236         return NULL;
237     return string_to_char(session->banner);
238 }
239 
240 void ssh_disconnect(SSH_SESSION *session){
241     STRING *str;
242     if(session->fd!= -1) {
243         packet_clear_out(session);
244         buffer_add_u8(session->out_buffer,SSH2_MSG_DISCONNECT);
245         buffer_add_u32(session->out_buffer,htonl(SSH2_DISCONNECT_BY_APPLICATION));
246         str=string_from_char("Bye Bye");
247         buffer_add_ssh_string(session->out_buffer,str);
248         free(str);
249         packet_send(session);
250         close(session->fd);
251         session->fd=-1;
252     }
253     session->alive=0;
254     ssh_cleanup(session);
255 }
256 
257 const char *ssh_copyright(){
258     return LIBSSH_VERSION " (c) 2003-2004 Aris Adamantiadis (aris@0xbadc0de.be)"
259                 " Distributed under the LGPL, please refer to COPYING file for informations"
260                 " about your rights" ;
261 }
5772780 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11/libssh]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2005-03-04 19:54:59