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