5772801 [rkeene@sledge /home/rkeene/projects/libssh-win32/v0.11/src/libssh-0.11-win32/libssh]$ cat -n options.c
  1 /* options.c */
  2 /* handle pre-connection options */
  3 /*
  4 Copyright 2003 Aris Adamantiadis
  5 
  6 This file is part of the SSH Library
  7 
  8 The SSH Library is free software; you can redistribute it and/or modify
  9 it under the terms of the GNU Lesser General Public License as published by
 10 the Free Software Foundation; either version 2.1 of the License, or (at your
 11 option) any later version.
 12 
 13 The SSH Library is distributed in the hope that it will be useful, but
 14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 16 License for more details.
 17 
 18 You should have received a copy of the GNU Lesser General Public License
 19 along with the SSH Library; see the file COPYING.  If not, write to
 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 21 MA 02111-1307, USA. */
 22 #include "libssh/priv.h"
 23 #include <stdio.h>
 24 #include <stdlib.h>
 25 #include <unistd.h>
 26 #include <string.h>
 27 #ifdef HAVE_PWD_H
 28 #include <pwd.h>
 29 #endif
 30 #include <sys/types.h>
 31 
 32 SSH_OPTIONS *options_new(){
 33     SSH_OPTIONS *option=malloc(sizeof(SSH_OPTIONS));
 34     memset(option,0,sizeof(SSH_OPTIONS));
 35     option->port=22; /* set the default port */
 36     option->fd=-1; 
 37     return option;
 38 }
 39 
 40 void options_set_port(SSH_OPTIONS *opt, unsigned int port){
 41     opt->port=port&0xffff;
 42 }
 43 SSH_OPTIONS *options_copy(SSH_OPTIONS *opt){
 44     SSH_OPTIONS *ret=options_new();    
 45     int i;
 46     ret->fd=opt->fd;
 47     ret->port=opt->port;
 48     if(opt->username)
 49         ret->username=strdup(opt->username);
 50     if(opt->host)
 51         ret->host=strdup(opt->host);
 52     if(opt->bindaddr)
 53         ret->host=strdup(opt->bindaddr);
 54     if(opt->identity)
 55         ret->identity=strdup(opt->identity);
 56     if(opt->ssh_dir)
 57         ret->ssh_dir=strdup(opt->ssh_dir);
 58     if(opt->known_hosts_file)
 59         ret->known_hosts_file=strdup(opt->known_hosts_file);
 60     for(i=0;i<10;++i)
 61         if(opt->wanted_methods[i])
 62             ret->wanted_methods[i]=strdup(opt->wanted_methods[i]);
 63     ret->passphrase_function=opt->passphrase_function;
 64     ret->connect_status_function=opt->connect_status_function;
 65     ret->connect_status_arg=opt->connect_status_arg;
 66     ret->timeout=opt->timeout;
 67     ret->timeout_usec=opt->timeout_usec;
 68     return ret;
 69 }
 70 
 71 void options_free(SSH_OPTIONS *opt){
 72     int i;
 73     if(opt->username)
 74         free(opt->username);
 75     if(opt->identity)
 76         free(opt->identity);
 77     /* we don't touch the banner. if the implementation did use it, they have to free it */
 78     if(opt->host)
 79         free(opt->host);
 80     if(opt->bindaddr)
 81         free(opt->bindaddr);
 82     if(opt->ssh_dir)
 83         free(opt->ssh_dir);
 84     for(i=0;i<10;i++)
 85         if(opt->wanted_methods[i])
 86             free(opt->wanted_methods[i]);
 87     memset(opt,0,sizeof(SSH_OPTIONS));
 88     free(opt);
 89 }
 90 
 91 
 92 void options_set_host(SSH_OPTIONS *opt, const char *hostname){
 93     char *ptr=strdup(hostname);
 94     char *ptr2=strchr(ptr,'@');
 95     if(opt->host) // don't leak memory
 96         free(opt->host);
 97     if(ptr2){
 98         *ptr2=0;
 99         opt->host=strdup(ptr2+1);
100         if(opt->username)
101             free(opt->username);
102         opt->username=strdup(ptr);
103         free(ptr);
104     } else
105         opt->host=ptr;
106 }
107 
108 void options_set_fd(SSH_OPTIONS *opt, int fd){
109     opt->fd=fd;
110 }
111 
112 void options_set_bindaddr(SSH_OPTIONS *opt, char *bindaddr){
113     opt->bindaddr=strdup(bindaddr);
114 }
115 
116 void options_set_username(SSH_OPTIONS *opt,char *username){
117     opt->username=strdup(username);
118 }
119 
120 void options_set_ssh_dir(SSH_OPTIONS *opt, char *dir){
121     char buffer[1024];
122     snprintf(buffer,1024,dir,ssh_get_user_home_dir());
123     opt->ssh_dir=strdup(buffer);
124 }
125 void options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir){
126     char buffer[1024];
127     snprintf(buffer,1024,dir,ssh_get_user_home_dir());
128     opt->known_hosts_file=strdup(buffer);
129 }
130 
131 void options_set_identity(SSH_OPTIONS *opt, char *identity){
132     char buffer[1024];
133     snprintf(buffer,1024,identity,ssh_get_user_home_dir());
134     opt->identity=strdup(buffer);
135 }
136 
137 /* what's the deal here ? some options MUST be set before authentication or key exchange,
138  * otherwise default values are going to be used. what must be configurable :
139  * Public key certification method *
140  * key exchange method (dh-sha1 for instance)*
141  * c->s, s->c ciphers *
142  * c->s s->c macs *
143  * c->s s->c compression */
144 
145 /* they all return 0 if all went well, 1 or !=0 if not. the most common error is unmatched algo (unimplemented) */
146 /* don't forget other errors can happen if no matching algo is found in sshd answer */
147 
148 int options_set_wanted_method(SSH_OPTIONS *opt,int method, char *list){
149     if(method > 9 || method < 0){
150         ssh_set_error(NULL,SSH_FATAL,"method %d out of range",method);
151         return -1;
152     }
153     if( (!opt->use_nonexisting_algo) && !verify_existing_algo(method,list)){
154         ssh_set_error(NULL,SSH_FATAL,"Setting method : no algorithm for method \"%s\"
	(%s)\n",ssh_kex_nums[method],list);
155         return -1;
156     }
157     if(opt->wanted_methods[method])
158         free(opt->wanted_methods[method]);
159     opt->wanted_methods[method]=strdup(list);    
160     return 0;
161 }
162 
163 static char *get_username_from_uid(int uid){
164 #ifdef HAVE_GETPWENT
165     struct passwd *pwd;
166     char *user;
167     while((pwd=getpwent())){
168         if(pwd->pw_uid == uid){
169             user=strdup(pwd->pw_name);
170             endpwent();
171             return user;
172         }
173     }
174     endpwent();
175 #endif
176     ssh_set_error(NULL,SSH_FATAL,"uid %d doesn't exist !",uid);
177     return NULL;
178 }
179 
180 /* this function must be called when no specific username has been asked. it has to guess it */
181 int options_default_username(SSH_OPTIONS *opt){
182     char *user;
183     if(opt->username)
184         return 0;
185     user=getenv("USER");
186     if(user){
187         opt->username=strdup(user);
188         return 0;
189     }
190 
191 #ifdef HAVE_GETUID
192     user=get_username_from_uid(getuid());
193     if(user){
194         opt->username=user;
195         return 0;
196     }
197 #endif
198     return -1;
199 }
200 
201 int options_default_ssh_dir(SSH_OPTIONS *opt){
202     char buffer[256];
203     if(opt->ssh_dir)
204         return 0;
205     snprintf(buffer,256,"%s/.ssh/",ssh_get_user_home_dir());
206     opt->ssh_dir=strdup(buffer);
207     return 0;
208 }
209 
210 int options_default_known_hosts_file(SSH_OPTIONS *opt){
211     char buffer[1024];
212     if(opt->known_hosts_file)
213         return 0;
214     options_default_ssh_dir(opt);
215     snprintf(buffer,1024,"%s/known_hosts",opt->ssh_dir);
216     opt->known_hosts_file=strdup(buffer);
217     return 0;
218 }
219 
220 void options_set_status_callback(SSH_OPTIONS *opt, void (*callback)(void *arg, float status), void *arg ){
221     opt->connect_status_function=callback;
222     opt->connect_status_arg=arg;
223 }
224 
225 void options_set_timeout(SSH_OPTIONS *opt, long seconds,long usec){
226     opt->timeout=seconds;
227     opt->timeout_usec=usec;
228 }
229 
230 SSH_OPTIONS *ssh_getopt(int *argcptr, char **argv){
231     int i;
232     int argc=*argcptr;
233     char *user=NULL;
234     int port=22;
235     int debuglevel=0;
236     int usersa=0;
237     int usedss=0;
238     int compress=0;
239     int cont=1;
240     char *cipher=NULL;
241     char *localaddr=NULL;
242     char *identity=NULL;
243     char **save=malloc(argc * sizeof(char *));
244     int current=0;
245 
246     int saveoptind=optind; /* need to save 'em */
247     int saveopterr=opterr;
248     SSH_OPTIONS *options;
249     opterr=0; /* shut up getopt */
250     while(cont && ((i=getopt(argc,argv,"c:i:Cl:p:vb:rd12"))!=-1)){
251 
252         switch(i){
253             case 'l':
254                 user=optarg;
255                 break;
256             case 'p':
257                 port=atoi(optarg)&0xffff;
258                 break;
259             case 'v':
260                 debuglevel++;
261                 break;
262             case 'r':
263                 usersa++;
264                 break;
265             case 'd':
266                 usedss++;
267                 break;
268             case 'c':
269                 cipher=optarg;
270                 break;
271             case 'i':
272                 identity=optarg;
273                 break;
274             case 'b':
275                 localaddr=optarg;
276                 break;
277             case 'C':
278                 compress++;
279                 break;
280             case '2':
281                 break; /* only ssh2 support till now */
282             case '1':
283                 ssh_set_error(NULL,SSH_FATAL,"libssh does not support SSH1 protocol");
284                 cont =0;
285                 break;
286             default:
287                 {
288                 char opt[3]="- ";
289                 opt[1]=optopt;
290                 save[current++]=strdup(opt);
291                 if(optarg)
292                     save[current++]=argv[optind+1];
293             }
294         }
295     }
296     opterr=saveopterr;
297     while(optind < argc)
298         save[current++]=argv[optind++];
299         
300     if(usersa && usedss){
301         ssh_set_error(NULL,SSH_FATAL,"either RSA or DSS must be chosen");
302         cont=0;
303     }
304     ssh_set_verbosity(debuglevel);
305     optind=saveoptind;
306     if(!cont){
307         free(save);
308         return NULL;
309     }
310     /* first recopy the save vector into original's */
311     for(i=0;i<current;i++)
312         argv[i+1]=save[i]; // don't erase argv[0]
313     argv[current+1]=NULL;
314     *argcptr=current+1;
315     free(save);
316     /* set a new option struct */
317     options=options_new();
318     if(compress){
319         if(options_set_wanted_method(options,KEX_COMP_C_S,"zlib"))
320             cont=0;
321         if(options_set_wanted_method(options,KEX_COMP_S_C,"zlib"))
322             cont=0;
323     }
324     if(cont &&cipher){
325         if(options_set_wanted_method(options,KEX_CRYPT_C_S,cipher))
326             cont=0;
327         if(cont && options_set_wanted_method(options,KEX_CRYPT_S_C,cipher))
328             cont=0;
329     }
330     if(cont && usersa)
331         if(options_set_wanted_method(options,KEX_HOSTKEY,"ssh-rsa"))
332             cont=0;
333     if(cont && usedss)
334         if(options_set_wanted_method(options,KEX_HOSTKEY,"ssh-dss"))
335             cont=0;
336     if(cont && user)
337         options_set_username(options,user);
338     if(cont && identity)
339         options_set_identity(options,identity);
340     if(cont && localaddr)
341         options_set_bindaddr(options,localaddr);
342     options_set_port(options,port);
343     if(!cont){
344         options_free(options);
345         return NULL;
346     } else
347         return options;   
348 }
5772802 [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