5772794 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11-win32/libssh]$ cat -n kex.c
  1 /* kex.c is used well, in key exchange :-) */
  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 <string.h>
 23 #include <stdlib.h>
 24 #include "libssh/priv.h"
 25 #include "libssh/ssh2.h"
 26 #ifdef HAVE_OPENSSL_BLOWFISH_H
 27 #define BLOWFISH "blowfish-cbc"
 28 #else
 29 #define BLOWFISH ""
 30 #endif
 31 #ifdef HAVE_OPENSSL_AES_H
 32 #define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
 33 #else
 34 #define AES ""
 35 #endif
 36 #ifdef HAVE_LIBZ
 37 #define ZLIB "none,zlib"
 38 #else
 39 #define ZLIB "none"
 40 #endif
 41 char *default_methods[]={
 42     "diffie-hellman-group1-sha1","ssh-dss,ssh-rsa",AES BLOWFISH, AES BLOWFISH,
 43     "hmac-sha1","hmac-sha1","none","none","","",NULL };
 44 char *supported_methods[]={
 45     "diffie-hellman-group1-sha1","ssh-dss,ssh-rsa",AES BLOWFISH,AES BLOWFISH,
 46     "hmac-sha1","hmac-sha1",ZLIB,ZLIB,"","",NULL };
 47 /* descriptions of the key exchange packet */
 48 char *ssh_kex_nums[]={
 49     "kex algos","server host key algo","encryption client->server","encryption server->client",
 50     "mac algo client->server","mac algo server->client","compression algo client->server",
 51     "compression algo server->client","languages client->server","languages server->client",NULL};
 52 
 53 /* tokenize will return a token of strings delimited by ",". the first element has to be freed */
 54 static char **tokenize(char *chain){
 55     char **tokens;
 56     int n=1;
 57     int i=0;
 58     char *ptr=chain=strdup(chain);
 59     while(*ptr){
 60         if(*ptr==','){
 61             n++;
 62             *ptr=0;
 63         }
 64         ptr++;
 65     }
 66     /* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
 67     tokens=malloc(sizeof(char *) * (n+1) ); /* +1 for the null */
 68     ptr=chain;
 69     for(i=0;i<n;i++){
 70         tokens[i]=ptr;
 71         while(*ptr)
 72             ptr++; // find a zero
 73         ptr++; // then go one step further
 74     }
 75     tokens[i]=NULL;
 76     return tokens;
 77 }
 78 
 79 /* same as tokenize(), but with spaces instead of ',' */
 80 char **space_tokenize(char *chain){
 81     char **tokens;
 82     int n=1;
 83     int i=0;
 84     char *ptr=chain=strdup(chain);
 85     while(*ptr==' ')
 86         ++ptr; /* skip initial spaces */
 87     while(*ptr){
 88         if(*ptr==' '){
 89             n++; /* count one token per word */
 90             *ptr=0;
 91             while(*(ptr+1)==' '){ /* don't count if the tokens have more than 2 spaces */
 92                 *(ptr++)=0;
 93             }
 94         }
 95         ptr++;
 96     }
 97     /* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
 98     tokens=malloc(sizeof(char *) * (n+1) ); /* +1 for the null */
 99     ptr=chain; /* we don't pass the initial spaces because the "chain" pointer is needed by the caller */
100                     /* function to free the tokens. */
101     for(i=0;i<n;i++){
102         tokens[i]=ptr;
103         if(i!=n-1){
104             while(*ptr)
105                 ptr++; // find a zero
106             while(!*(ptr+1))
107                 ++ptr; /* if the zero is followed by other zeros, go through them */
108             ptr++; // then go one step further
109         }
110     }
111     tokens[i]=NULL;
112     return tokens;
113 }
114 
115 /* find_matching gets 2 parameters : a list of available objects (in_d), separated by colons,*/
116 /* and a list of prefered objects (what_d) */
117 /* it will return a strduped pointer on the first prefered object found in the available objects list */
118 
119 static char *find_matching(char *in_d, char *what_d){
120     char ** tok_in, **tok_what;
121     int i_in, i_what;
122     char *ret;
123     
124     if( ! (in_d && what_d))
125         return NULL; /* don't deal with null args */
126     ssh_say(3,"find_matching(\"%s\",\"%s\") = ",in_d,what_d);
127     tok_in=tokenize(in_d);
128     tok_what=tokenize(what_d);
129     for(i_in=0; tok_in[i_in]; ++i_in){
130         for(i_what=0; tok_what[i_what] ; ++i_what){
131             if(!strcmp(tok_in[i_in],tok_what[i_what])){
132                 /* match */            
133                 ssh_say(3,"\"%s\"\n",tok_in[i_in]);
134                 ret=strdup(tok_in[i_in]);
135                 /* free the tokens */
136                 free(tok_in[0]);
137                 free(tok_what[0]);
138                 free(tok_in);
139                 free(tok_what);
140                 return ret;
141             }
142         }
143     }
144     ssh_say(3,"NULL\n");
145     free(tok_in[0]);
146     free(tok_what[0]);
147     free(tok_in);
148     free(tok_what);
149     return NULL;
150 }
151 
152 int ssh_get_kex(SSH_SESSION *session,int server_kex ){
153     STRING *str;
154     char *strings[10];
155     int i;
156     if(packet_wait(session,SSH2_MSG_KEXINIT,1))
157         return -1;
158     if(buffer_get_data(session->in_buffer,session->server_kex.cookie,16)!=16){
159         ssh_set_error((session->connected?session:NULL),SSH_FATAL,"get_kex(): no cookie in packet");
160         return -1;
161     }
162     hashbufin_add_cookie(session,session->server_kex.cookie);
163     memset(strings,0,sizeof(char *)*10);
164     for(i=0;i<10;++i){
165         str=buffer_get_ssh_string(session->in_buffer);
166         if(!str)
167             break;
168         if(str){
169             buffer_add_ssh_string(session->in_hashbuf,str);
170             strings[i]=string_to_char(str);
171             free(str);
172         } else
173             strings[i]=NULL;
174     }
175     /* copy the server kex info into an array of strings */
176     if(server_kex){
177         session->client_kex.methods=malloc( 10 * sizeof(char **));
178         for(i=0;i<10;++i)
179             session->client_kex.methods[i]=strings[i];
180     } else { // client     
181         session->server_kex.methods=malloc( 10 * sizeof(char **));
182         for(i=0;i<10;++i)
183             session->server_kex.methods[i]=strings[i];
184     }
185     return 0;
186 }
187 
188 void list_kex(KEX *kex){
189     int i=0;
190 #ifdef DEBUG_CRYPTO
191     ssh_print_hexa("session cookie",kex->cookie,16);
192 #endif
193     for(i=0;i<10;i++){
194         ssh_say(2,"%s : %s\n",ssh_kex_nums[i],kex->methods[i]);
195     }
196 }
197 
198 /* set_kex basicaly look at the option structure of the session and set the output kex message */
199 /* it must be aware of the server kex message */
200 /* it can fail if option is null, not any user specified kex method matches the server one, if not any default kex
	matches */
201 
202 int set_kex(SSH_SESSION *session){
203     KEX *server = &session->server_kex;
204     KEX *client=&session->client_kex;
205     SSH_OPTIONS *options=session->options;
206     int i;
207     char *wanted;
208     /* the client might ask for a specific cookie to be sent. useful for server debugging */
209     if(options->wanted_cookie)
210         memcpy(client->cookie,options->wanted_cookie,16);
211     else
212         ssh_get_random(client->cookie,16);
213     client->methods=malloc(10 * sizeof(char **));
214     memset(client->methods,0,10*sizeof(char **));
215     for (i=0;i<10;i++){
216         if(!(wanted=options->wanted_methods[i]))
217             wanted=default_methods[i];
218         client->methods[i]=find_matching(server->methods[i],wanted);
219         if(!client->methods[i] && i < KEX_LANG_C_S){
220             ssh_set_error((session->connected?session:NULL),SSH_FATAL,"kex error : did not find one of algos %s in list
	%s for %s",
221             wanted,server->methods[i],ssh_kex_nums[i]);
222             return -1;
223         } else {
224             if(i>=KEX_LANG_C_S && !client->methods[i])
225                 client->methods[i]=strdup(""); // we can safely do that for languages
226         }
227     }
228     return 0;
229 }
230 
231 /* this function only sends the predefined set of kex methods */    
232 void send_kex(SSH_SESSION *session, int server_kex){
233     STRING *str;
234     int i=0;
235     KEX *kex=(server_kex ? &session->server_kex : &session->client_kex);
236     packet_clear_out(session);
237     buffer_add_u8(session->out_buffer,SSH2_MSG_KEXINIT);
238     buffer_add_data(session->out_buffer,kex->cookie,16);
239     hashbufout_add_cookie(session);
240     list_kex(kex);
241     for(i=0;i<10;i++){
242         str=string_from_char(kex->methods[i]);
243         buffer_add_ssh_string(session->out_hashbuf,str);
244         buffer_add_ssh_string(session->out_buffer,str);
245         free(str);
246     }
247     i=0;
248     buffer_add_u8(session->out_buffer,0);
249     buffer_add_u32(session->out_buffer,0);
250     packet_send(session);
251 }
252 
253 /* returns 1 if at least one of the name algos is in the default algorithms table */
254 int verify_existing_algo(int algo, char *name){
255     char *ptr;
256     if(algo>9 || algo <0)
257         return -1;
258     ptr=find_matching(supported_methods[algo],name);
259     if(ptr){
260         free(ptr);
261         return 1;
262     }
263     return 0;
264 }
5772795 [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: 2005-03-04 19:54:59