~ubuntu-branches/ubuntu/trusty/libssh/trusty-security

« back to all changes in this revision

Viewing changes to libssh/options.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2009-12-12 14:29:12 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20091212142912-ha5g2iibt6nfnjq8
Tags: 0.4.0-1
* New upstream release.
  - Bump soname
  - Adjust .symbols file
* Readd static library in -dev package
* Let dh_lintian install override file
* debian/README.Debian: Update file
* debian/rules: Add list-missing rule

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
 * MA 02111-1307, USA.
23
23
 */
24
24
 
 
25
#include "config.h"
25
26
#include <stdio.h>
26
27
#include <stdlib.h>
27
 
#include <unistd.h>
28
28
#include <string.h>
29
29
#ifndef _WIN32
30
30
#include <pwd.h>
 
31
#else
 
32
#include <winsock2.h>
31
33
#endif
32
34
#include <sys/types.h>
33
35
#include "libssh/priv.h"
34
 
 
35
 
/** \defgroup ssh_options SSH Options
36
 
 * \brief options settings for a new SSH session
37
 
 */
38
 
/** \addtogroup ssh_options
39
 
 * @{ */
40
 
 
41
 
/** This structure is freed automaticaly by ssh_disconnect()
42
 
 * when you use it. \n
43
 
 * It can be used by only one ssh_connect(), not more.\n
44
 
 * also by default, ssh1 support is not allowed 
45
 
 *
46
 
 * \brief initializes a new option structure
47
 
 * \returns an empty intialized option structure.
48
 
 * \see ssh_options_getopt()
49
 
*/
50
 
 
51
 
SSH_OPTIONS *ssh_options_new(void) {
52
 
    SSH_OPTIONS *option;
53
 
 
54
 
    option = malloc(sizeof(SSH_OPTIONS));
55
 
    if (option == NULL) {
56
 
      return NULL;
57
 
    }
58
 
 
59
 
    memset(option,0,sizeof(SSH_OPTIONS));
60
 
    option->port=22; /* set the default port */
61
 
    option->fd=-1;
62
 
    option->ssh2allowed=1;
63
 
#ifdef WITH_SSH1
64
 
    option->ssh1allowed=1;
65
 
#else
66
 
    option->ssh1allowed=0;
 
36
#include "libssh/session.h"
 
37
#include "libssh/misc.h"
 
38
#ifdef WITH_SERVER
 
39
#include "libssh/server.h"
67
40
#endif
68
 
    option->bindport=22;
69
 
    return option;
70
 
}
71
 
 
72
 
/**
73
 
 * @brief Set port to connect or to bind for a connection.
74
 
 *
75
 
 * @param opt           The options structure to use.
76
 
 *
77
 
 * @param port          The port to connect or to bind.
78
 
 *
79
 
 * @return 0 on success, < 0 on error.
80
 
 */
81
 
int ssh_options_set_port(SSH_OPTIONS *opt, unsigned int port) {
82
 
  if (opt == NULL) {
83
 
    return -1;
84
 
  }
85
 
 
86
 
  opt->port = port & 0xffff;
87
 
  opt->bindport = port & 0xffff;
88
 
 
89
 
  return 0;
90
 
}
91
 
 
92
 
/**
93
 
 * @brief Duplicate an option structure.
 
41
 
 
42
/**
 
43
 * @brief Duplicate the options of a session structure.
94
44
 *
95
45
 * If you make several sessions with the same options this is useful. You
96
46
 * cannot use twice the same option structure in ssh_session_connect.
101
51
 *
102
52
 * @see ssh_session_connect()
103
53
 */
104
 
SSH_OPTIONS *ssh_options_copy(SSH_OPTIONS *opt) {
105
 
  SSH_OPTIONS *new = NULL;
 
54
int ssh_options_copy(ssh_session src, ssh_session *dest) {
 
55
  ssh_session new;
106
56
  int i;
107
57
 
108
 
  if (opt == NULL) {
109
 
    return NULL;
110
 
  }
111
 
 
112
 
  new = ssh_options_new();
113
 
  if (new == NULL) {
114
 
    return NULL;
115
 
  }
116
 
 
117
 
  if (opt->username) {
118
 
    new->username = strdup(opt->username);
 
58
  if (src == NULL || dest == NULL || *dest == NULL) {
 
59
    return -1;
 
60
  }
 
61
 
 
62
  new = *dest;
 
63
 
 
64
  if (src->username) {
 
65
    new->username = strdup(src->username);
119
66
    if (new->username == NULL) {
120
 
      goto err;
121
 
    }
122
 
  }
123
 
  if (opt->host) {
124
 
    new->host = strdup(opt->host);
125
 
    if (new->host == NULL) {
126
 
      goto err;
127
 
    }
128
 
  }
129
 
  if (opt->bindaddr) {
130
 
    new->host = strdup(opt->bindaddr);
131
 
    if (new->host == NULL) {
132
 
      goto err;
133
 
    }
134
 
  }
135
 
  if (opt->identity) {
136
 
    new->identity=strdup(opt->identity);
 
67
      return -1;
 
68
    }
 
69
  }
 
70
 
 
71
  if (src->host) {
 
72
    new->host = strdup(src->host);
 
73
    if (new->host == NULL) {
 
74
      return -1;
 
75
    }
 
76
  }
 
77
 
 
78
  if (src->identity) {
 
79
    new->identity = strdup(src->identity);
137
80
    if (new->identity == NULL) {
138
 
      return NULL;
139
 
    }
140
 
  }
141
 
  if (opt->ssh_dir) {
142
 
    new->ssh_dir = strdup(opt->ssh_dir);
143
 
    if (new->ssh_dir == NULL) {
144
 
      goto err;
145
 
    }
146
 
  }
147
 
  if (opt->known_hosts_file) {
148
 
    new->known_hosts_file = strdup(opt->known_hosts_file);
149
 
    if (new->known_hosts_file == NULL) {
150
 
      goto err;
151
 
    }
152
 
  }
153
 
  if (opt->dsakey) {
154
 
    new->dsakey = strdup(opt->dsakey);
155
 
    if (new->dsakey == NULL) {
156
 
      goto err;
157
 
    }
158
 
  }
159
 
  if (opt->rsakey) {
160
 
    new->rsakey = strdup(opt->rsakey);
161
 
    if (new->rsakey == NULL) {
162
 
      goto err;
163
 
    }
164
 
  }
 
81
      return -1;
 
82
    }
 
83
  }
 
84
 
 
85
  if (src->sshdir) {
 
86
    new->sshdir = strdup(src->sshdir);
 
87
    if (new->sshdir == NULL) {
 
88
      return -1;
 
89
    }
 
90
  }
 
91
 
 
92
  if (src->knownhosts) {
 
93
    new->knownhosts = strdup(src->knownhosts);
 
94
    if (new->knownhosts == NULL) {
 
95
      return -1;
 
96
    }
 
97
  }
 
98
 
165
99
  for (i = 0; i < 10; ++i) {
166
 
    if (opt->wanted_methods[i]) {
167
 
      new->wanted_methods[i] = strdup(opt->wanted_methods[i]);
 
100
    if (src->wanted_methods[i]) {
 
101
      new->wanted_methods[i] = strdup(src->wanted_methods[i]);
168
102
      if (new->wanted_methods[i] == NULL) {
169
 
        goto err;
 
103
        return -1;
170
104
      }
171
105
    }
172
106
  }
173
107
 
174
 
  new->fd = opt->fd;
175
 
  new->port = opt->port;
176
 
  new->auth_function = opt->auth_function;
177
 
  new->auth_userdata = opt->auth_userdata;
178
 
  new->connect_status_function = opt->connect_status_function;
179
 
  new->connect_status_arg = opt->connect_status_arg;
180
 
  new->timeout = opt->timeout;
181
 
  new->timeout_usec = opt->timeout_usec;
182
 
  new->ssh2allowed = opt->ssh2allowed;
183
 
  new->ssh1allowed = opt->ssh1allowed;
184
 
  new->log_function = opt->log_function;
185
 
  new->log_verbosity = opt->log_verbosity;
186
 
 
187
 
  return new;
188
 
err:
189
 
  ssh_options_free(new);
190
 
  return NULL;
191
 
}
192
 
 
193
 
/**
194
 
 * @brief Frees an option structure.
195
 
 *
196
 
 * @param opt           Option structure to free.
197
 
 */
198
 
void ssh_options_free(SSH_OPTIONS *opt) {
199
 
  int i;
200
 
 
201
 
  if (opt == NULL) {
202
 
    return;
203
 
  }
204
 
 
205
 
  /*
206
 
   * We don't touch the banner. If the implementation
207
 
   * did use it, they have to free it
208
 
   */
209
 
 
210
 
  SAFE_FREE(opt->username);
211
 
  SAFE_FREE(opt->host);
212
 
  SAFE_FREE(opt->identity);
213
 
  SAFE_FREE(opt->bindaddr);
214
 
  SAFE_FREE(opt->ssh_dir);
215
 
  SAFE_FREE(opt->known_hosts_file);
216
 
  SAFE_FREE(opt->dsakey);
217
 
  SAFE_FREE(opt->rsakey);
218
 
 
219
 
  for (i = 0; i < 10; i++) {
220
 
    if (opt->wanted_methods[i]) {
221
 
      free(opt->wanted_methods[i]);
222
 
    }
223
 
  }
224
 
  ZERO_STRUCTP(opt);
225
 
  SAFE_FREE(opt);
226
 
}
227
 
 
228
 
/**
229
 
 * @brief Set destination hostname
230
 
 *
231
 
 * @param opt           The option structure to use.
232
 
 *
233
 
 * @param hostname      The host name to connect.
234
 
 *
235
 
 * @return 0 on succes, < 0 on error.
236
 
 */
237
 
int ssh_options_set_host(SSH_OPTIONS *opt, const char *hostname){
238
 
  char *h;
239
 
  char *p;
240
 
 
241
 
  if (opt == NULL || hostname == NULL) {
242
 
    return -1;
243
 
  }
244
 
 
245
 
  h = strdup(hostname);
246
 
  if (h == NULL) {
247
 
    return -1;
248
 
  }
249
 
  p = strchr(h, '@');
250
 
 
251
 
  SAFE_FREE(opt->host);
252
 
 
253
 
  if (p) {
254
 
    *p = '\0';
255
 
    opt->host = strdup(p + 1);
256
 
    if (opt->host == NULL) {
257
 
      SAFE_FREE(h);
258
 
      return -1;
259
 
    }
260
 
 
261
 
    SAFE_FREE(opt->username);
262
 
    opt->username = strdup(h);
263
 
    SAFE_FREE(h);
264
 
    if (opt->username == NULL) {
265
 
      return -1;
266
 
    }
267
 
  } else {
268
 
    opt->host = h;
269
 
  }
270
 
 
271
 
  return 0;
272
 
}
273
 
 
274
 
/**
275
 
 * @brief Set the username for authentication
276
 
 *
277
 
 * @param opt           The options structure to use.
278
 
 *
279
 
 * @param username      The username to authenticate.
280
 
 *
281
 
 * @return 0 on success, -1 on error.
282
 
 *
283
 
 * @bug this should not be set at options time
284
 
 */
285
 
int ssh_options_set_username(SSH_OPTIONS *opt, const char *username) {
286
 
  if (opt == NULL || username == NULL) {
287
 
    return -1;
288
 
  }
289
 
 
290
 
  SAFE_FREE(opt->username);
291
 
  opt->username = strdup(username);
292
 
  if (opt->username == NULL) {
293
 
    return -1;
294
 
  }
295
 
 
296
 
  return 0;
297
 
}
298
 
 
299
 
/**
300
 
 * @brief Set a file descriptor for connection.
301
 
 *
302
 
 * If you wish to open the socket yourself for a reason or another, set the
303
 
 * file descriptor. Don't forget to use ssh_option_set_hostname() as the
304
 
 * hostname is used as a key in the known_host mechanism.
305
 
 *
306
 
 * @param opt           The options structure to use.
307
 
 *
308
 
 * @param fd            An opened file descriptor to use.
309
 
 *
310
 
 * @return 0 on success, < 0 on error.
311
 
 */
312
 
int ssh_options_set_fd(SSH_OPTIONS *opt, socket_t fd) {
313
 
  if (opt == NULL) {
314
 
    return -1;
315
 
  }
316
 
  opt->fd = fd;
317
 
 
318
 
  return 0;
319
 
}
320
 
 
321
 
/**
322
 
 * @brief Set the local address and port binding.
323
 
 *
324
 
 * In case your client has multiple IP adresses, select the local address and
325
 
 * port to use for the socket.\n
326
 
 * If the address or port is not bindable, it may be impossible to connect.
327
 
 *
328
 
 * @param opt           The options structure to use.
329
 
 *
330
 
 * @param bindaddr      The bind address in form of hostname or ip address.
331
 
 *
332
 
 * @param port          The port number to bind.
333
 
 *
334
 
 * @return 0 on success, < 0 on error.
335
 
 */
336
 
int ssh_options_set_bind(SSH_OPTIONS *opt, const char *bindaddr, int port) {
337
 
  if (opt == NULL || bindaddr == NULL) {
338
 
    return -1;
339
 
  }
340
 
 
341
 
  SAFE_FREE(opt->bindaddr);
342
 
  opt->bindaddr = strdup(bindaddr);
343
 
  if (opt->bindaddr == NULL) {
344
 
    return -1;
345
 
  }
346
 
  opt->bindport = port;
347
 
 
348
 
  return 0;
349
 
}
350
 
 
351
 
/**
352
 
 * @brief Set the ssh directory.
353
 
 *
354
 
 * The ssh directory is used for files like known_hosts and identity (public
355
 
 * and private keys)
356
 
 *
357
 
 * @param opt           The options structure to use.
358
 
 *
359
 
 * @param dir           The directory to set. It may include "%s" which will be
360
 
 *                      replaced by the user home directory.
361
 
 *
362
 
 * @return 0 on success, < 0 on error.
363
 
 *
364
 
 * @see ssh_options_set_user_home_dir()
365
 
 */
366
 
int ssh_options_set_ssh_dir(SSH_OPTIONS *opt, const char *dir) {
367
 
  char buffer[1024] = {0};
368
 
 
369
 
  if (opt == NULL || dir == NULL) {
370
 
    return -1;
371
 
  }
372
 
 
373
 
  snprintf(buffer, 1024, dir, ssh_get_user_home_dir());
374
 
  SAFE_FREE(opt->ssh_dir);
375
 
  opt->ssh_dir = strdup(buffer);
376
 
  if (opt->ssh_dir == NULL) {
377
 
    return -1;
378
 
  }
379
 
 
380
 
  return 0;
381
 
}
382
 
 
383
 
/**
384
 
 * @brief Set the known hosts file name.
385
 
 *
386
 
 * The known hosts file is used to certify remote hosts are genuine.
387
 
 *
388
 
 * @param opt           The options structure to use.
389
 
 *
390
 
 * @param dir           The path to the file including its name. "%s" will be
391
 
 *                      substitued with the user home directory.
392
 
 *
393
 
 * @return 0 on success, < 0 on error.
394
 
 *
395
 
 * @see ssh_options_set_user_home_dir()
396
 
 */
397
 
int ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, const char *dir){
398
 
  char buffer[1024] = {0};
399
 
 
400
 
  if (opt == NULL || dir == NULL) {
401
 
    return -1;
402
 
  }
403
 
 
404
 
  snprintf(buffer, 1024, dir, ssh_get_user_home_dir());
405
 
  SAFE_FREE(opt->known_hosts_file);
406
 
  opt->known_hosts_file = strdup(buffer);
407
 
  if (opt->known_hosts_file == NULL) {
408
 
    return -1;
409
 
  }
410
 
 
411
 
  return 0;
412
 
}
413
 
 
414
 
/**
415
 
 * @brief Set the identity file name.
416
 
 *
417
 
 * The identity file is used authenticate with public key.
418
 
 *
419
 
 * @param opt           The options structure to use.
420
 
 *
421
 
 * @param identity      The path to the file including its name. "%s" will be
422
 
 *                      substitued with the user home directory.
423
 
 *
424
 
 * @return 0 on success, < 0 on error.
425
 
 *
426
 
 * @see ssh_options_set_user_home_dir()
427
 
 */
428
 
int ssh_options_set_identity(SSH_OPTIONS *opt, const char *identity){
429
 
  char buffer[1024] = {0};
430
 
 
431
 
  if (opt == NULL || identity == NULL) {
432
 
    return -1;
433
 
  }
434
 
 
435
 
  snprintf(buffer, 1024, identity, ssh_get_user_home_dir());
436
 
  SAFE_FREE(opt->identity);
437
 
  opt->identity = strdup(buffer);
438
 
  if (opt->identity == NULL) {
439
 
    return -1;
440
 
  }
441
 
 
442
 
  return 0;
443
 
}
444
 
 
445
 
/**
446
 
 * @brief Set the path to the dsa ssh host key.
447
 
 *
448
 
 * @param  opt          The options structure to use.
449
 
 *
450
 
 * @param  dsakey       The path to the dsa key to set.
451
 
 *
452
 
 * @return 0 on success, < 0 on error.
453
 
 */
454
 
int ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, const char *dsakey) {
455
 
  if (opt == NULL || dsakey == NULL) {
456
 
    return -1;
457
 
  }
458
 
 
459
 
  opt->dsakey = strdup(dsakey);
460
 
  if (opt->dsakey == NULL) {
461
 
    return -1;
462
 
  }
463
 
 
464
 
  return 0;
465
 
}
466
 
 
467
 
/**
468
 
 * @brief Set the path to the ssh host rsa key.
469
 
 *
470
 
 * @param  opt          The options structure to use.
471
 
 *
472
 
 * @param  rsakey       The path to the rsa key to set.
473
 
 *
474
 
 * @return 0 on success, < 0 on error.
475
 
 */
476
 
int ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, const char *rsakey) {
477
 
  if (opt == NULL || rsakey == NULL) {
478
 
    return -1;
479
 
  }
480
 
 
481
 
  opt->rsakey = strdup(rsakey);
482
 
  if (opt->rsakey == NULL) {
483
 
    return -1;
484
 
  }
485
 
 
486
 
  return 0;
487
 
}
488
 
 
489
 
/**
490
 
 * @brief Set the server banner sent to clients.
491
 
 *
492
 
 * @param opt           The options structure to use.
493
 
 *
494
 
 * @param banner        A text banner to be shown.
495
 
 *
496
 
 * @return 0 on success, < 0 on error.
497
 
 */
498
 
int ssh_options_set_banner(SSH_OPTIONS *opt, const char *banner) {
499
 
  if (opt == NULL || banner == NULL) {
500
 
    return -1;
501
 
  }
502
 
 
503
 
  SAFE_FREE(opt->banner);
504
 
  opt->banner = strdup(banner);
505
 
  if (opt->banner == NULL) {
506
 
    return -1;
507
 
  }
508
 
 
509
 
  return 0;
510
 
}
511
 
 
512
 
/**
513
 
 * @brief Set the algorithms to be used for cryptography and compression.
514
 
 *
515
 
 * The methods are:\n
516
 
 * KEX_HOSTKEY (server public key type) : ssh-rsa or ssh-dss\n
517
 
 * KEX_CRYPT_C_S (symmetric cipher client to server)\n
518
 
 * KEX_CRYPT_S_C (symmetric cipher server to client)\n
519
 
 * KEX_COMP_C_S (Compression client to server): zlib or none\n
520
 
 * KEX_COMP_S_C (Compression server to client): zlib or none\n
521
 
 * You don't have to use this function if using the default ciphers
522
 
 * is okay for you\n
523
 
 * in order to enable compression client to server, do\n
524
 
 * @code
525
 
 * ret = ssh_options_set_wanted_algos(opt,KEX_COMP_C_S,"zlib");
526
 
 * @endcode
527
 
 *
528
 
 * @param opt           The options structure to use.
529
 
 *
530
 
 * @param algo          The method which needs to be changed.
531
 
 *
532
 
 * @param list          A list of algorithms to be used, in order of preference
533
 
 *                      and separated by commas.
534
 
 *
535
 
 * @return 0 on success, < 0 on error
536
 
 */
537
 
int ssh_options_set_wanted_algos(SSH_OPTIONS *opt, int algo, const char *list) {
538
 
  if (opt == NULL || list == NULL) {
539
 
    return -1;
540
 
  }
541
 
 
542
 
  if(algo > SSH_LANG_S_C || algo < 0) {
543
 
    ssh_set_error(opt, SSH_REQUEST_DENIED, "algo %d out of range", algo);
544
 
    return -1;
545
 
  }
546
 
 
547
 
  if ((!opt->use_nonexisting_algo) && !verify_existing_algo(algo, list)) {
548
 
    ssh_set_error(opt, SSH_REQUEST_DENIED, "Setting method: no algorithm "
549
 
        "for method \"%s\" (%s)\n", ssh_kex_nums[algo], list);
550
 
    return -1;
551
 
  }
552
 
 
553
 
  SAFE_FREE(opt->wanted_methods[algo]);
554
 
  opt->wanted_methods[algo] = strdup(list);
555
 
  if (opt->wanted_methods[algo] == NULL) {
556
 
    return -1;
557
 
  }
 
108
  new->fd = src->fd;
 
109
  new->port = src->port;
 
110
  new->callbacks = src->callbacks;
 
111
  new->timeout = src->timeout;
 
112
  new->timeout_usec = src->timeout_usec;
 
113
  new->ssh2 = src->ssh2;
 
114
  new->ssh1 = src->ssh1;
 
115
  new->log_verbosity = src->log_verbosity;
558
116
 
559
117
  return 0;
560
118
}
561
119
 
562
120
#ifndef _WIN32
563
 
static char *get_username_from_uid(SSH_OPTIONS *opt, uid_t uid){
 
121
static char *get_username_from_uid(ssh_session session, uid_t uid){
564
122
    struct passwd *pwd = NULL;
 
123
    char *name;
565
124
 
566
125
    pwd = getpwuid(uid);
567
126
 
568
127
    if (pwd == NULL) {
569
 
      ssh_set_error(opt,SSH_FATAL,"uid %d doesn't exist !",uid);
570
 
      return NULL;
571
 
    }
572
 
 
573
 
    return strdup(pwd->pw_name);
574
 
}
575
 
#endif
576
 
 
577
 
/* this function must be called when no specific username has been asked. it has to guess it */
578
 
int ssh_options_default_username(SSH_OPTIONS *opt) {
579
 
  char *user = NULL;
580
 
 
581
 
  if (opt->username) {
582
 
    return 0;
583
 
  }
584
 
 
585
 
#ifndef _WIN32
586
 
  user = get_username_from_uid(opt,getuid());
587
 
  if (user) {
588
 
    opt->username = user;
589
 
    return 0;
590
 
  }
591
 
#else
592
 
  DWORD Size = 0;
593
 
  GetUserName(NULL, &Size); //Get Size
594
 
  user = malloc(Size);
595
 
  if (user == NULL) {
596
 
    return -1;
597
 
  }
598
 
  if (GetUserName(user, &Size)) {
599
 
    opt->username=user;
600
 
    return 0;
601
 
  } else {
602
 
    SAFE_FREE(user);
603
 
  }
604
 
#endif
605
 
  return -1;
606
 
}
607
 
 
608
 
int ssh_options_default_ssh_dir(SSH_OPTIONS *opt) {
609
 
  char buffer[256] = {0};
610
 
 
611
 
  if (opt->ssh_dir) {
612
 
    return 0;
613
 
  }
614
 
 
615
 
  snprintf(buffer, 256, "%s/.ssh/", ssh_get_user_home_dir());
616
 
  opt->ssh_dir = strdup(buffer);
617
 
  if (opt->ssh_dir == NULL) {
618
 
    return -1;
619
 
  }
620
 
 
621
 
  return 0;
622
 
}
623
 
 
624
 
int ssh_options_default_known_hosts_file(SSH_OPTIONS *opt) {
625
 
  char buffer[1024] = {0};
626
 
 
627
 
  if (opt->known_hosts_file) {
628
 
    return 0;
629
 
  }
630
 
 
631
 
  if (ssh_options_default_ssh_dir(opt) < 0) {
632
 
    return -1;
633
 
  }
634
 
 
635
 
  snprintf(buffer, 1024, "%s/known_hosts", opt->ssh_dir);
636
 
  opt->known_hosts_file = strdup(buffer);
637
 
  if (opt->known_hosts_file == NULL) {
638
 
    return -1;
639
 
  }
640
 
 
641
 
  return 0;
642
 
}
643
 
 
644
 
/**
645
 
 * @brief Set a callback to show connection status in realtime.
646
 
 *
647
 
 * During ssh_connect(), libssh will call the callback with status from
648
 
 * 0.0 to 1.0
649
 
 *
650
 
 * @param opt           The options structure to use.
651
 
 *
652
 
 * @param callback      A function pointer to a callback in form
653
 
 *                      f(void *userarg, float status).
654
 
 *
655
 
 * @param arg           The value to be given as argument to the callback
656
 
 *                      function when it is called.
657
 
 *
658
 
 * @return 0 on success, < 0 on error.
659
 
 *
660
 
 * @see ssh_connect()
661
 
 */
662
 
int ssh_options_set_status_callback(SSH_OPTIONS *opt,
663
 
    void (*callback)(void *arg, float status), void *arg) {
664
 
  if (opt == NULL || callback == NULL) {
665
 
    return -1;
666
 
  }
667
 
 
668
 
  opt->connect_status_function = callback;
669
 
  opt->connect_status_arg = arg;
670
 
 
671
 
  return 0;
672
 
}
673
 
 
674
 
/**
675
 
 * @brief Set a timeout for the connection.
676
 
 *
677
 
 * @param opt           The options structure to use.
678
 
 *
679
 
 * @param seconds       Number of seconds.
680
 
 *
681
 
 * @param usec          Number of micro seconds.
682
 
 *
683
 
 * @return 0 on success, < 0 on error.
684
 
 *
685
 
 * @bug Currently it only timeouts the socket connection, not the
686
 
 *      complete exchange.
687
 
 */
688
 
int ssh_options_set_timeout(SSH_OPTIONS *opt, long seconds, long usec) {
689
 
  if (opt == NULL) {
690
 
    return -1;
691
 
  }
692
 
 
693
 
  opt->timeout=seconds;
694
 
  opt->timeout_usec=usec;
695
 
 
696
 
  return 0;
697
 
}
698
 
 
699
 
/**
700
 
 * @brief Allow or deny the connection to SSH1 servers.
701
 
 *
702
 
 * Default value is 0 (no connection to SSH1 servers).
703
 
 *
704
 
 * @param opt           The options structure to use.
705
 
 *
706
 
 * @param allow         Non zero value allow ssh1.
707
 
 *
708
 
 * @return 0 on success, < 0 on error.
709
 
 */
710
 
int ssh_options_allow_ssh1(SSH_OPTIONS *opt, int allow) {
711
 
  if (opt == NULL) {
712
 
    return -1;
713
 
  }
714
 
 
715
 
  if (allow) {
716
 
    opt->ssh1allowed = 1;
717
 
  } else {
718
 
    opt->ssh1allowed = 0;
719
 
  }
720
 
 
721
 
  return 0;
722
 
}
723
 
 
724
 
/**
725
 
 * @brief Allow or deny the connection to SSH2 servers.
726
 
 *
727
 
 * Default value is 1 (allow connection to SSH2 servers).
728
 
 *
729
 
 * @param opt           The options structure to use.
730
 
 *
731
 
 * @param allow         Non zero values allow ssh2.
732
 
 *
733
 
 * @return 0 on success, < 0 on error.
734
 
 */
735
 
int ssh_options_allow_ssh2(SSH_OPTIONS *opt, int allow) {
736
 
  if (opt == NULL) {
737
 
    return -1;
738
 
  }
739
 
 
740
 
  if (allow) {
741
 
    opt->ssh2allowed = 1;
742
 
  } else {
743
 
    opt->ssh2allowed = 0;
744
 
  }
745
 
 
746
 
  return 0;
747
 
}
748
 
 
749
 
/**
750
 
 * @brief Change the writer callback for logging.
751
 
 *
752
 
 * Default is a write on stderr.
753
 
 *
754
 
 * @param opt           The options structure to use.
755
 
 *
756
 
 * @param callback      A callback function for the printing.
757
 
 *
758
 
 * @return 0 on success, < 0 on error.
759
 
 *
760
 
 * @warning The message string may contain format string characters.
761
 
 */
762
 
int ssh_options_set_log_function(SSH_OPTIONS *opt,
763
 
    void (*callback)(const char *message, SSH_SESSION *session, int priority)) {
764
 
  if (opt == NULL || callback == NULL) {
765
 
    return -1;
766
 
  }
767
 
 
768
 
  opt->log_function = callback;
769
 
 
770
 
  return 0;
771
 
}
772
 
 
773
 
/**
774
 
 * @brief Set the session logging priority.
775
 
 *
776
 
 * @param opt           The options structure to use.
777
 
 *
778
 
 * @param verbosity     The verbosity of the messages. Every log smaller or
779
 
 *                      equal to verbosity will be shown\n
780
 
 *                      SSH_LOG_NOLOG No logging \n
781
 
 *                      SSH_LOG_RARE Rare conditions or warnings\n
782
 
 *                      SSH_LOG_ENTRY Api-accessible entrypoints\n
783
 
 *                      SSH_LOG_PACKET Packet id and size\n
784
 
 *                      SSH_LOG_FUNCTIONS function entering and leaving\n
785
 
 *
786
 
 * @return 0 on success, < 0 on error.
787
 
 */
788
 
int ssh_options_set_log_verbosity(SSH_OPTIONS *opt, int verbosity) {
789
 
  if (opt == NULL) {
790
 
    return -1;
791
 
  }
792
 
 
793
 
  opt->log_verbosity = verbosity;
794
 
 
795
 
  return 0;
796
 
}
 
128
      ssh_set_error(session, SSH_FATAL, "uid %d doesn't exist !", uid);
 
129
      return NULL;
 
130
    }
 
131
 
 
132
    name = strdup(pwd->pw_name);
 
133
 
 
134
    if (name == NULL) {
 
135
      ssh_set_error_oom(session);
 
136
      return NULL;
 
137
    }
 
138
 
 
139
    return name;
 
140
}
 
141
#endif
 
142
 
 
143
int ssh_options_set_algo(ssh_session session, int algo,
 
144
    const char *list) {
 
145
  if (!verify_existing_algo(algo, list)) {
 
146
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
147
        "Setting method: no algorithm for method \"%s\" (%s)\n",
 
148
        ssh_kex_nums[algo], list);
 
149
    return -1;
 
150
  }
 
151
 
 
152
  SAFE_FREE(session->wanted_methods[algo]);
 
153
  session->wanted_methods[algo] = strdup(list);
 
154
  if (session->wanted_methods[algo] == NULL) {
 
155
    ssh_set_error_oom(session);
 
156
    return -1;
 
157
  }
 
158
 
 
159
  return 0;
 
160
}
 
161
 
 
162
char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) {
 
163
        char *new;
 
164
 
 
165
        if (value[0] == '~' && value[1] == '/') {
 
166
                char *homedir = ssh_get_user_home_dir();
 
167
    size_t lv, lh;
 
168
 
 
169
    if (homedir == NULL) {
 
170
      return NULL;
 
171
    }
 
172
    lv = strlen(value + 1);
 
173
    lh = strlen(homedir);
 
174
 
 
175
                new = malloc(lv + lh + 1);
 
176
                if (new == NULL) {
 
177
      ssh_set_error_oom(session);
 
178
      SAFE_FREE(homedir);
 
179
                        return NULL;
 
180
    }
 
181
                memcpy(new, homedir, lh);
 
182
    SAFE_FREE(homedir);
 
183
                memcpy(new + lh, value + 1, lv + 1);
 
184
                return new;
 
185
        }
 
186
        if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) {
 
187
                size_t lv, ls;
 
188
                if (session->sshdir == NULL) {
 
189
                        if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0)
 
190
                                return NULL;
 
191
                }
 
192
 
 
193
                value += 7;
 
194
                lv = strlen(value);
 
195
                ls = strlen(session->sshdir);
 
196
 
 
197
                new = malloc(lv + ls + 1);
 
198
                if (new == NULL) {
 
199
      ssh_set_error_oom(session);
 
200
                        return NULL;
 
201
    }
 
202
                memcpy(new, session->sshdir, ls);
 
203
                memcpy(new + ls, value, lv + 1);
 
204
                return new;
 
205
        }
 
206
  new = strdup(value);
 
207
  if (new == NULL) {
 
208
    ssh_set_error_oom(session);
 
209
    return NULL;
 
210
  }
 
211
  return new;
 
212
}
 
213
 
 
214
/**
 
215
 * @brief This function can set all possible ssh options.
 
216
 *
 
217
 * @param  session          An allocated ssh option structure.
 
218
 *
 
219
 * @param  type         The option type to set. This could be one of the
 
220
 *                      following:
 
221
 *
 
222
 *                      SSH_OPTIONS_HOST:
 
223
 *                        The hostname or ip address to connect to (string).
 
224
 *
 
225
 *                      SSH_OPTIONS_PORT:
 
226
 *                        The port to connect to (integer).
 
227
 *
 
228
 *                      SSH_OPTIONS_PORT_STR:
 
229
 *                        The port to connect to (string).
 
230
 *
 
231
 *                      SSH_OPTIONS_FD:
 
232
 *                        The file descriptor to use (socket_t).
 
233
 *
 
234
 *                        If you wish to open the socket yourself for a reason
 
235
 *                        or another, set the file descriptor. Don't forget to
 
236
 *                        set the hostname as the hostname is used as a key in
 
237
 *                        the known_host mechanism.
 
238
 *
 
239
 *                      SSH_OPTIONS_USER:
 
240
 *                        The username for authentication (string).
 
241
 *
 
242
 *                        If the value is NULL, the username is set to the
 
243
 *                        default username.
 
244
 *
 
245
 *                      SSH_OPTIONS_SSH_DIR:
 
246
 *                        Set the ssh directory (format string).
 
247
 *
 
248
 *                        If the value is NULL, the directory is set to the
 
249
 *                        default ssh directory.
 
250
 *
 
251
 *                        The ssh directory is used for files like known_hosts
 
252
 *                        and identity (private and public key). It may include
 
253
 *                        "%s" which will be replaced by the user home
 
254
 *                        directory.
 
255
 *
 
256
 *                      SSH_OPTIONS_KNOWNHOSTS:
 
257
 *                        Set the known hosts file name (format string).
 
258
 *
 
259
 *                        If the value is NULL, the directory is set to the
 
260
 *                        default known hosts file, normally ~/.ssh/known_hosts.
 
261
 *
 
262
 *                        The known hosts file is used to certify remote hosts
 
263
 *                        are genuine. It may include "%s" which will be
 
264
 *                        replaced by the user home directory.
 
265
 *
 
266
 *                      SSH_OPTIONS_IDENTITY:
 
267
 *                        Set the identity file name (format string).
 
268
 *
 
269
 *                        By default identity, id_dsa and id_rsa are checked.
 
270
 *
 
271
 *                        The identity file used authenticate with public key.
 
272
 *                        It may include "%s" which will be replaced by the
 
273
 *                        user home directory.
 
274
 *
 
275
 *                      SSH_OPTIONS_TIMEOUT:
 
276
 *                        Set a timeout for the connection in seconds (integer).
 
277
 *
 
278
 *                      SSH_OPTIONS_TIMEOUT_USEC:
 
279
 *                        Set a timeout for the connection in micro seconds
 
280
 *                        (integer).
 
281
 *
 
282
 *                      SSH_OPTIONS_SSH1:
 
283
 *                        Allow or deny the connection to SSH1 servers
 
284
 *                        (integer).
 
285
 *
 
286
 *                      SSH_OPTIONS_SSH2:
 
287
 *                        Allow or deny the connection to SSH2 servers
 
288
 *                        (integer).
 
289
 *
 
290
 *                      SSH_OPTIONS_LOG_VERBOSITY:
 
291
 *                        Set the session logging verbosity (integer).
 
292
 *
 
293
 *                        The verbosity of the messages. Every log smaller or
 
294
 *                        equal to verbosity will be shown.
 
295
 *                          SSH_LOG_NOLOG: No logging
 
296
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
297
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
298
 *                          SSH_LOG_PACKET: Packet id and size
 
299
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
300
 *
 
301
 *                      SSH_OPTIONS_LOG_VERBOSITY_STR:
 
302
 *                        Set the session logging verbosity (string).
 
303
 *
 
304
 *                        The verbosity of the messages. Every log smaller or
 
305
 *                        equal to verbosity will be shown.
 
306
 *                          SSH_LOG_NOLOG: No logging
 
307
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
308
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
309
 *                          SSH_LOG_PACKET: Packet id and size
 
310
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
311
 *
 
312
 *                          See the corresponding numbers in libssh.h.
 
313
 *
 
314
 *                      SSH_OPTTIONS_AUTH_CALLBACK:
 
315
 *                        Set a callback to use your own authentication function
 
316
 *                        (function pointer).
 
317
 *
 
318
 *                      SSH_OPTTIONS_AUTH_USERDATA:
 
319
 *                        Set the user data passed to the authentication function
 
320
 *                        (generic pointer).
 
321
 *
 
322
 *                      SSH_OPTTIONS_LOG_CALLBACK:
 
323
 *                        Set a callback to use your own logging function
 
324
 *                        (function pointer).
 
325
 *
 
326
 *                      SSH_OPTTIONS_LOG_USERDATA:
 
327
 *                        Set the user data passed to the logging function
 
328
 *                        (generic pointer).
 
329
 *
 
330
 *                      SSH_OPTTIONS_STATUS_CALLBACK:
 
331
 *                        Set a callback to show connection status in realtime
 
332
 *                        (function pointer).
 
333
 *
 
334
 *                        fn(void *arg, float status)
 
335
 *
 
336
 *                        During ssh_connect(), libssh will call the callback
 
337
 *                        with status from 0.0 to 1.0.
 
338
 *
 
339
 *                      SSH_OPTTIONS_STATUS_ARG:
 
340
 *                        Set the status argument which should be passed to the
 
341
 *                        status callback (generic pointer).
 
342
 *
 
343
 *                      SSH_OPTIONS_CIPHERS_C_S:
 
344
 *                        Set the symmetric cipher client to server (string,
 
345
 *                        comma-separated list).
 
346
 *
 
347
 *                      SSH_OPTIONS_CIPHERS_S_C:
 
348
 *                        Set the symmetric cipher server to client (string,
 
349
 *                        comma-separated list).
 
350
 *
 
351
 *                      SSH_OPTIONS_COMPRESSION_C_S:
 
352
 *                        Set the compression to use for client to server
 
353
 *                        communication (string, "none" or "zlib").
 
354
 *
 
355
 *                      SSH_OPTIONS_COMPRESSION_S_C:
 
356
 *                        Set the compression to use for server to client
 
357
 *                        communication (string, "none" or "zlib").
 
358
 *
 
359
 * @param  value        The value to set. This is a generic pointer and the
 
360
 *                      datatype which is used should be set according to the
 
361
 *                      type set.
 
362
 *
 
363
 * @return              0 on success, < 0 on error.
 
364
 */
 
365
int ssh_options_set(ssh_session session, enum ssh_options_e type,
 
366
    const void *value) {
 
367
  char *p, *q;
 
368
  long int i;
 
369
 
 
370
  if (session == NULL) {
 
371
    return -1;
 
372
  }
 
373
 
 
374
  switch (type) {
 
375
    case SSH_OPTIONS_HOST:
 
376
      q = strdup(value);
 
377
      if (q == NULL) {
 
378
        ssh_set_error_oom(session);
 
379
        return -1;
 
380
      }
 
381
      p = strchr(q, '@');
 
382
 
 
383
      SAFE_FREE(session->host);
 
384
 
 
385
      if (p) {
 
386
        *p = '\0';
 
387
        session->host = strdup(p + 1);
 
388
        if (session->host == NULL) {
 
389
          SAFE_FREE(q);
 
390
          ssh_set_error_oom(session);
 
391
          return -1;
 
392
        }
 
393
 
 
394
        SAFE_FREE(session->username);
 
395
        session->username = strdup(q);
 
396
        SAFE_FREE(q);
 
397
        if (session->username == NULL) {
 
398
          ssh_set_error_oom(session);
 
399
          return -1;
 
400
        }
 
401
      } else {
 
402
        session->host = q;
 
403
      }
 
404
      break;
 
405
    case SSH_OPTIONS_PORT:
 
406
      if (value == NULL) {
 
407
        session->port = 22 & 0xffff;
 
408
      } else {
 
409
        int *x = (int *) value;
 
410
 
 
411
        session->port = *x & 0xffff;
 
412
      }
 
413
      break;
 
414
    case SSH_OPTIONS_PORT_STR:
 
415
      if (value == NULL) {
 
416
        session->port = 22 & 0xffff;
 
417
      } else {
 
418
        q = strdup(value);
 
419
        if (q == NULL) {
 
420
          ssh_set_error_oom(session);
 
421
          return -1;
 
422
        }
 
423
        i = strtol(q, &p, 10);
 
424
        if (q == p) {
 
425
          SAFE_FREE(q);
 
426
        }
 
427
        SAFE_FREE(q);
 
428
 
 
429
        session->port = i & 0xffff;
 
430
      }
 
431
      break;
 
432
    case SSH_OPTIONS_USER:
 
433
      SAFE_FREE(session->username);
 
434
      if (value == NULL) { /* set default username */
 
435
#ifdef _WIN32
 
436
        DWORD size = 0;
 
437
        GetUserName(NULL, &size); //Get Size
 
438
        q = malloc(size);
 
439
        if (q == NULL) {
 
440
          ssh_set_error_oom(session);
 
441
          return -1;
 
442
        }
 
443
        if (GetUserName(q, &size)) {
 
444
          session->username = q;
 
445
        } else {
 
446
          SAFE_FREE(q);
 
447
          return -1;
 
448
        }
 
449
#else /* _WIN32 */
 
450
        q = get_username_from_uid(session, getuid());
 
451
        if (q == NULL) {
 
452
          return -1;
 
453
        }
 
454
        session->username = q;
 
455
#endif /* _WIN32 */
 
456
      } else { /* username provided */
 
457
        session->username = strdup(value);
 
458
        if (session->username == NULL) {
 
459
          ssh_set_error_oom(session);
 
460
          return -1;
 
461
        }
 
462
      }
 
463
      break;
 
464
    case SSH_OPTIONS_SSH_DIR:
 
465
      if (value == NULL) {
 
466
        SAFE_FREE(session->sshdir);
 
467
        /* TODO: why ~/.ssh/ instead of ~/.ssh ? */
 
468
 
 
469
        session->sshdir = dir_expand_dup(session, "~/.ssh/", 0);
 
470
        if (session->sshdir == NULL) {
 
471
          return -1;
 
472
        }
 
473
      } else {
 
474
        SAFE_FREE(session->sshdir);
 
475
        session->sshdir = dir_expand_dup(session, value, 0);
 
476
        if (session->sshdir == NULL) {
 
477
          return -1;
 
478
        }
 
479
      }
 
480
      break;
 
481
    case SSH_OPTIONS_IDENTITY:
 
482
 
 
483
      if (value == NULL) {
 
484
        ssh_set_error_invalid(session, __FUNCTION__);
 
485
        return -1;
 
486
      }
 
487
      SAFE_FREE(session->identity);
 
488
      session->identity = dir_expand_dup(session, value, 1);
 
489
      if (session->identity == NULL) {
 
490
        return -1;
 
491
      }
 
492
      break;
 
493
    case SSH_OPTIONS_KNOWNHOSTS:
 
494
      if (value == NULL) {
 
495
        SAFE_FREE(session->knownhosts);
 
496
        session->knownhosts = dir_expand_dup(session,
 
497
            "SSH_DIR/known_hosts", 1);
 
498
        if (session->knownhosts == NULL) {
 
499
          return -1;
 
500
        }
 
501
      } else {
 
502
        SAFE_FREE(session->knownhosts);
 
503
        session->knownhosts = dir_expand_dup(session, value, 1);
 
504
        if (session->knownhosts == NULL) {
 
505
          return -1;
 
506
        }
 
507
      }
 
508
      break;
 
509
    case SSH_OPTIONS_TIMEOUT:
 
510
      if (value == NULL) {
 
511
        ssh_set_error_invalid(session, __FUNCTION__);
 
512
        return -1;
 
513
      } else {
 
514
        long *x = (long *) value;
 
515
 
 
516
        session->timeout = *x & 0xffffffff;
 
517
      }
 
518
      break;
 
519
    case SSH_OPTIONS_TIMEOUT_USEC:
 
520
      if (value == NULL) {
 
521
        ssh_set_error_invalid(session, __FUNCTION__);
 
522
        return -1;
 
523
      } else {
 
524
        long *x = (long *) value;
 
525
 
 
526
        session->timeout_usec = *x & 0xffffffff;
 
527
      }
 
528
      break;
 
529
    case SSH_OPTIONS_SSH1:
 
530
      if (value == NULL) {
 
531
        ssh_set_error_invalid(session, __FUNCTION__);
 
532
        return -1;
 
533
      } else {
 
534
        int *x = (int *) value;
 
535
        session->ssh1 = *x;
 
536
      }
 
537
      break;
 
538
    case SSH_OPTIONS_SSH2:
 
539
      if (value == NULL) {
 
540
        ssh_set_error_invalid(session, __FUNCTION__);
 
541
        return -1;
 
542
      } else {
 
543
        int *x = (int *) value;
 
544
        session->ssh2 = *x & 0xffff;
 
545
      }
 
546
      break;
 
547
    case SSH_OPTIONS_LOG_VERBOSITY:
 
548
      if (value == NULL) {
 
549
        ssh_set_error_invalid(session, __FUNCTION__);
 
550
        return -1;
 
551
      } else {
 
552
        int *x = (int *) value;
 
553
 
 
554
        session->log_verbosity = *x & 0xffff;
 
555
      }
 
556
      break;
 
557
    case SSH_OPTIONS_LOG_VERBOSITY_STR:
 
558
      if (value == NULL) {
 
559
        session->log_verbosity = 0 & 0xffff;
 
560
      } else {
 
561
        q = strdup(value);
 
562
        if (q == NULL) {
 
563
          ssh_set_error_oom(session);
 
564
          return -1;
 
565
        }
 
566
        i = strtol(q, &p, 10);
 
567
        if (q == p) {
 
568
          SAFE_FREE(q);
 
569
        }
 
570
        SAFE_FREE(q);
 
571
 
 
572
        session->log_verbosity = i & 0xffff;
 
573
      }
 
574
      break;
 
575
    case SSH_OPTIONS_CIPHERS_C_S:
 
576
      if (value == NULL) {
 
577
        ssh_set_error_invalid(session, __FUNCTION__);
 
578
        return -1;
 
579
      } else {
 
580
        if (ssh_options_set_algo(session, SSH_CRYPT_C_S, value) < 0)
 
581
          return -1;
 
582
      }
 
583
      break;
 
584
    case SSH_OPTIONS_CIPHERS_S_C:
 
585
      if (value == NULL) {
 
586
        ssh_set_error_invalid(session, __FUNCTION__);
 
587
        return -1;
 
588
      } else {
 
589
        if (ssh_options_set_algo(session, SSH_CRYPT_S_C, value) < 0)
 
590
          return -1;
 
591
      }
 
592
      break;
 
593
    case SSH_OPTIONS_COMPRESSION_C_S:
 
594
      if (value == NULL) {
 
595
        ssh_set_error_invalid(session, __FUNCTION__);
 
596
        return -1;
 
597
      } else {
 
598
        if (ssh_options_set_algo(session, SSH_COMP_C_S, value) < 0)
 
599
          return -1;
 
600
      }
 
601
      break;
 
602
    case SSH_OPTIONS_COMPRESSION_S_C:
 
603
      if (value == NULL) {
 
604
        ssh_set_error_invalid(session, __FUNCTION__);
 
605
        return -1;
 
606
      } else {
 
607
        if (ssh_options_set_algo(session, SSH_COMP_S_C, value) < 0)
 
608
          return -1;
 
609
      }
 
610
      break;
 
611
    default:
 
612
      ssh_set_error(session, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
 
613
      return -1;
 
614
    break;
 
615
  }
 
616
 
 
617
  return 0;
 
618
}
 
619
 
 
620
#ifdef WITH_SERVER
 
621
static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
 
622
    const char *list) {
 
623
  if (!verify_existing_algo(algo, list)) {
 
624
    ssh_set_error(sshbind, SSH_REQUEST_DENIED,
 
625
        "Setting method: no algorithm for method \"%s\" (%s)\n",
 
626
        ssh_kex_nums[algo], list);
 
627
    return -1;
 
628
  }
 
629
 
 
630
  SAFE_FREE(sshbind->wanted_methods[algo]);
 
631
  sshbind->wanted_methods[algo] = strdup(list);
 
632
  if (sshbind->wanted_methods[algo] == NULL) {
 
633
    ssh_set_error_oom(sshbind);
 
634
    return -1;
 
635
  }
 
636
 
 
637
  return 0;
 
638
}
 
639
 
 
640
/**
 
641
 * @brief This function can set all possible ssh bind options.
 
642
 *
 
643
 * @param  session      An allocated ssh option structure.
 
644
 *
 
645
 * @param  type         The option type to set. This could be one of the
 
646
 *                      following:
 
647
 *
 
648
 *                      SSH_BIND_OPTIONS_LOG_VERBOSITY:
 
649
 *                        Set the session logging verbosity (integer).
 
650
 *
 
651
 *                        The verbosity of the messages. Every log smaller or
 
652
 *                        equal to verbosity will be shown.
 
653
 *                          SSH_LOG_NOLOG: No logging
 
654
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
655
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
656
 *                          SSH_LOG_PACKET: Packet id and size
 
657
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
658
 *
 
659
 *                      SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
 
660
 *                        Set the session logging verbosity (integer).
 
661
 *
 
662
 *                        The verbosity of the messages. Every log smaller or
 
663
 *                        equal to verbosity will be shown.
 
664
 *                          SSH_LOG_NOLOG: No logging
 
665
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
666
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
667
 *                          SSH_LOG_PACKET: Packet id and size
 
668
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
669
 *
 
670
 *                      SSH_BIND_OPTIONS_BINDADDR:
 
671
 *                        Set the bind address.
 
672
 *
 
673
 *                      SSH_BIND_OPTIONS_BINDPORT:
 
674
 *                        Set the bind port, default is 22.
 
675
 *
 
676
 *                      SSH_BIND_OPTIONS_HOSTKEY:
 
677
 *                        Set the server public key type: ssh-rsa or ssh-dss
 
678
 *                        (string).
 
679
 *
 
680
 *                      SSH_BIND_OPTIONS_DSAKEY:
 
681
 *                        Set the path to the dsa ssh host key (string).
 
682
 *
 
683
 *                      SSH_BIND_OPTIONS_RSAKEY:
 
684
 *                        Set the path to the ssh host rsa key (string).
 
685
 *
 
686
 *                      SSH_BIND_OPTIONS_BANNER:
 
687
 *                        Set the server banner sent to clients (string).
 
688
 *
 
689
 * @param  value        The value to set. This is a generic pointer and the
 
690
 *                      datatype which is used should be set according to the
 
691
 *                      type set.
 
692
 *
 
693
 * @return              0 on success, < 0 on error.
 
694
 */
 
695
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
 
696
    const void *value) {
 
697
  char *p, *q;
 
698
  int i;
 
699
 
 
700
  if (sshbind == NULL) {
 
701
    return -1;
 
702
  }
 
703
 
 
704
  switch (type) {
 
705
    case SSH_BIND_OPTIONS_HOSTKEY:
 
706
      if (value == NULL) {
 
707
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
708
        return -1;
 
709
      } else {
 
710
        if (ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value) < 0)
 
711
          return -1;
 
712
      }
 
713
      break;
 
714
    case SSH_BIND_OPTIONS_BINDADDR:
 
715
      if (value == NULL) {
 
716
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
717
        return -1;
 
718
      } else {
 
719
        SAFE_FREE(sshbind->bindaddr);
 
720
        sshbind->bindaddr = strdup(value);
 
721
        if (sshbind->bindaddr == NULL) {
 
722
          ssh_set_error_oom(sshbind);
 
723
          return -1;
 
724
        }
 
725
      }
 
726
      break;
 
727
    case SSH_BIND_OPTIONS_BINDPORT:
 
728
      if (value == NULL) {
 
729
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
730
        return -1;
 
731
      } else {
 
732
        int *x = (int *) value;
 
733
        sshbind->bindport = *x & 0xffff;
 
734
      }
 
735
      break;
 
736
    case SSH_BIND_OPTIONS_BINDPORT_STR:
 
737
      if (value == NULL) {
 
738
        sshbind->bindport = 22 & 0xffff;
 
739
      } else {
 
740
        q = strdup(value);
 
741
        if (q == NULL) {
 
742
          ssh_set_error_oom(sshbind);
 
743
          return -1;
 
744
        }
 
745
        i = strtol(q, &p, 10);
 
746
        if (q == p) {
 
747
          SAFE_FREE(q);
 
748
        }
 
749
        SAFE_FREE(q);
 
750
 
 
751
        sshbind->bindport = i & 0xffff;
 
752
      }
 
753
      break;
 
754
    case SSH_BIND_OPTIONS_LOG_VERBOSITY:
 
755
      if (value == NULL) {
 
756
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
757
        return -1;
 
758
      } else {
 
759
        int *x = (int *) value;
 
760
        sshbind->log_verbosity = *x & 0xffff;
 
761
      }
 
762
      break;
 
763
    case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
 
764
      if (value == NULL) {
 
765
        sshbind->log_verbosity = 0;
 
766
      } else {
 
767
        q = strdup(value);
 
768
        if (q == NULL) {
 
769
          ssh_set_error_oom(sshbind);
 
770
          return -1;
 
771
        }
 
772
        i = strtol(q, &p, 10);
 
773
        if (q == p) {
 
774
          SAFE_FREE(q);
 
775
        }
 
776
        SAFE_FREE(q);
 
777
 
 
778
        sshbind->log_verbosity = i & 0xffff;
 
779
      }
 
780
      break;
 
781
    case SSH_BIND_OPTIONS_DSAKEY:
 
782
      if (value == NULL) {
 
783
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
784
        return -1;
 
785
      } else {
 
786
        SAFE_FREE(sshbind->dsakey);
 
787
        sshbind->dsakey = strdup(value);
 
788
        if (sshbind->dsakey == NULL) {
 
789
          ssh_set_error_oom(sshbind);
 
790
          return -1;
 
791
        }
 
792
      }
 
793
      break;
 
794
    case SSH_BIND_OPTIONS_RSAKEY:
 
795
      if (value == NULL) {
 
796
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
797
        return -1;
 
798
      } else {
 
799
        SAFE_FREE(sshbind->rsakey);
 
800
        sshbind->rsakey = strdup(value);
 
801
        if (sshbind->rsakey == NULL) {
 
802
          ssh_set_error_oom(sshbind);
 
803
          return -1;
 
804
        }
 
805
      }
 
806
      break;
 
807
    case SSH_BIND_OPTIONS_BANNER:
 
808
      if (value == NULL) {
 
809
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
810
        return -1;
 
811
      } else {
 
812
        SAFE_FREE(sshbind->banner);
 
813
        sshbind->banner = strdup(value);
 
814
        if (sshbind->banner == NULL) {
 
815
          ssh_set_error_oom(sshbind);
 
816
          return -1;
 
817
        }
 
818
      }
 
819
      break;
 
820
    default:
 
821
      ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unkown ssh option %d", type);
 
822
      return -1;
 
823
    break;
 
824
  }
 
825
 
 
826
  return 0;
 
827
}
 
828
#endif
 
829
 
797
830
/**
798
831
 * @brief Parse command line arguments.
799
832
 *
805
838
 * myssh -l user localhost\n
806
839
 * The command wont set the hostname value of options to localhost.
807
840
 *
808
 
 * @param options       An empty option structure pointer.
 
841
 * @param session       The session to configure.
809
842
 *
810
843
 * @param argcptr       The pointer to the argument count.
811
844
 *
813
846
 *
814
847
 * @returns 0 on success, < 0 on error.
815
848
 *
816
 
 * @see ssh_options_new()
 
849
 * @see ssh_session_new()
817
850
 */
818
 
int ssh_options_getopt(SSH_OPTIONS *options, int *argcptr, char **argv) {
 
851
int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
819
852
  char *user = NULL;
820
853
  char *cipher = NULL;
821
854
  char *localaddr = NULL;
822
855
  char *identity = NULL;
 
856
  char *port = NULL;
 
857
  char *bindport = NULL;
823
858
  char **save = NULL;
824
859
  int i = 0;
825
860
  int argc = *argcptr;
826
 
  int port = 22;
827
861
  int debuglevel = 0;
828
862
  int usersa = 0;
829
863
  int usedss = 0;
836
870
  int ssh1 = 0;
837
871
#endif
838
872
  int ssh2 = 1;
839
 
 
 
873
#ifdef _MSC_VER
 
874
    /* Not supported with a Microsoft compiler */
 
875
    return -1;
 
876
#else
840
877
  int saveoptind = optind; /* need to save 'em */
841
878
  int saveopterr = opterr;
842
879
 
843
880
  save = malloc(argc * sizeof(char *));
844
881
  if (save == NULL) {
 
882
    ssh_set_error_oom(session);
845
883
    return -1;
846
884
  }
847
885
 
848
886
  opterr = 0; /* shut up getopt */
849
 
  while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
 
887
  while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:t:rd12")) != -1)) {
850
888
    switch(i) {
851
889
      case 'l':
852
890
        user = optarg;
853
891
        break;
854
892
      case 'p':
855
 
        port = atoi(optarg) & 0xffff;
 
893
        port = optarg;
 
894
        break;
 
895
      case 't':
 
896
        bindport = optarg;
856
897
        break;
857
898
      case 'v':
858
899
        debuglevel++;
890
931
          save[current] = strdup(opt);
891
932
          if (save[current] == NULL) {
892
933
            SAFE_FREE(save);
 
934
            ssh_set_error_oom(session);
893
935
            return -1;
894
936
          }
895
937
          current++;
905
947
  }
906
948
 
907
949
  if (usersa && usedss) {
908
 
    ssh_set_error(options, SSH_FATAL, "Either RSA or DSS must be chosen");
 
950
    ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
909
951
    cont = 0;
910
952
  }
911
953
 
912
 
  ssh_options_set_log_verbosity(options, debuglevel);
 
954
  ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &debuglevel);
913
955
 
914
956
  optind = saveoptind;
915
957
 
929
971
 
930
972
  /* set a new option struct */
931
973
  if (compress) {
932
 
    if (ssh_options_set_wanted_algos(options, SSH_COMP_C_S, "zlib") < 0) {
 
974
    if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION_C_S, "zlib") < 0) {
933
975
      cont = 0;
934
976
    }
935
 
    if (ssh_options_set_wanted_algos(options, SSH_COMP_S_C, "zlib") < 0) {
 
977
    if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION_S_C, "zlib") < 0) {
936
978
      cont = 0;
937
979
    }
938
980
  }
939
981
 
940
982
  if (cont && cipher) {
941
 
    if (ssh_options_set_wanted_algos(options, SSH_CRYPT_C_S, cipher) < 0) {
942
 
      cont = 0;
943
 
    }
944
 
    if (cont && ssh_options_set_wanted_algos(options, SSH_CRYPT_S_C, cipher) < 0) {
945
 
      cont = 0;
946
 
    }
947
 
  }
948
 
 
949
 
  if (cont && usersa) {
950
 
    if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-rsa") < 0) {
951
 
      cont = 0;
952
 
    }
953
 
  }
954
 
 
955
 
  if (cont && usedss) {
956
 
    if (ssh_options_set_wanted_algos(options, SSH_HOSTKEYS, "ssh-dss") < 0) {
 
983
    if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) {
 
984
      cont = 0;
 
985
    }
 
986
    if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) {
957
987
      cont = 0;
958
988
    }
959
989
  }
960
990
 
961
991
  if (cont && user) {
962
 
    if (ssh_options_set_username(options, user) < 0) {
 
992
    if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
963
993
      cont = 0;
964
994
    }
965
995
  }
966
996
 
967
997
  if (cont && identity) {
968
 
    if (ssh_options_set_identity(options, identity) < 0) {
969
 
      cont = 0;
970
 
    }
971
 
  }
972
 
 
973
 
  if (cont && localaddr) {
974
 
    if (ssh_options_set_bind(options, localaddr, 0) < 0) {
975
 
      cont = 0;
976
 
    }
977
 
  }
978
 
 
979
 
  ssh_options_set_port(options, port);
980
 
  ssh_options_allow_ssh1(options, ssh1);
981
 
  ssh_options_allow_ssh2(options, ssh2);
 
998
    if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) {
 
999
      cont = 0;
 
1000
    }
 
1001
  }
 
1002
 
 
1003
  ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
 
1004
 
 
1005
  ssh_options_set(session, SSH_OPTIONS_SSH1, &ssh1);
 
1006
  ssh_options_set(session, SSH_OPTIONS_SSH2, &ssh2);
982
1007
 
983
1008
  if (!cont) {
984
 
    return -1;
 
1009
    return SSH_ERROR;
985
1010
  }
986
1011
 
987
 
  return 0;
 
1012
  return SSH_OK;
 
1013
#endif
988
1014
}
989
1015
 
990
1016
/**
991
 
 * @brief Set the authentication callback.
992
 
 *
993
 
 * @param opt           The options structure to use.
994
 
 *
995
 
 * @param cb            The callback function to use.
996
 
 *
997
 
 * @param userdata      A pointer to some user data you can pass to the
998
 
 *                      callback.
 
1017
 * @brief Parse the ssh config file.
 
1018
 *
 
1019
 * This should be the last call of all options, it may overwrite options which
 
1020
 * are already set. It requires that the host name is already set with
 
1021
 * ssh_options_set_host().
 
1022
 *
 
1023
 * @param  session      SSH session handle
 
1024
 *
 
1025
 * @param  filename     The options file to use, if NULL the default
 
1026
 *                      ~/.ssh/config will be used.
999
1027
 *
1000
1028
 * @return 0 on success, < 0 on error.
 
1029
 *
 
1030
 * @see ssh_options_set_host()
1001
1031
 */
1002
 
int ssh_options_set_auth_callback(SSH_OPTIONS *opt, ssh_auth_callback cb,
1003
 
    void *userdata) {
1004
 
  if (opt == NULL || cb == NULL) {
1005
 
    return -1;
1006
 
  }
1007
 
 
1008
 
  opt->auth_function = cb;
1009
 
  opt->auth_userdata = userdata;
1010
 
 
1011
 
  return 0;
 
1032
int ssh_options_parse_config(ssh_session session, const char *filename) {
 
1033
  char *expanded_filename;
 
1034
  int r;
 
1035
 
 
1036
  if (session == NULL) {
 
1037
    return -1;
 
1038
  }
 
1039
  if (session->host == NULL) {
 
1040
    ssh_set_error_invalid(session, __FUNCTION__);
 
1041
    return -1;
 
1042
  }
 
1043
 
 
1044
  /* set default filename */
 
1045
  if (filename == NULL) {
 
1046
    expanded_filename = dir_expand_dup(session, "SSH_DIR/config", 1);
 
1047
  } else {
 
1048
    expanded_filename = dir_expand_dup(session, filename, 1);
 
1049
  }
 
1050
  if (expanded_filename == NULL)
 
1051
    return -1;
 
1052
 
 
1053
  r = ssh_config_parse_file(session, expanded_filename);
 
1054
  free(expanded_filename);
 
1055
  return r;
1012
1056
}
1013
1057
 
1014
1058
/** @} */