~ubuntu-branches/ubuntu/precise/libssh/precise

« back to all changes in this revision

Viewing changes to src/options.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-15 15:48:07 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110615154807-3muklcqfftr1vtch
Tags: 0.5.0-2
* debian/patches/0002-Check-for-NULL-pointers-in-string-c.patch:
  Consolidate patch (Should fix previous REJECT)
* Support multiarch spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * options.c - handle pre-connection options
 
3
 *
 
4
 * This file is part of the SSH Library
 
5
 *
 
6
 * Copyright (c) 2003-2008 by Aris Adamantiadis
 
7
 * Copyright (c) 2009      by Andreas Schneider <mail@cynapses.org>
 
8
 *
 
9
 * The SSH Library is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU Lesser General Public License as published by
 
11
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 
12
 * option) any later version.
 
13
 *
 
14
 * The SSH Library is distributed in the hope that it will be useful, but
 
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
17
 * License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public License
 
20
 * along with the SSH Library; see the file COPYING.  If not, write to
 
21
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
22
 * MA 02111-1307, USA.
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#ifndef _WIN32
 
30
#include <pwd.h>
 
31
#else
 
32
#include <winsock2.h>
 
33
#endif
 
34
#include <sys/types.h>
 
35
#include "libssh/priv.h"
 
36
#include "libssh/session.h"
 
37
#include "libssh/misc.h"
 
38
#ifdef WITH_SERVER
 
39
#include "libssh/server.h"
 
40
#include "libssh/bind.h"
 
41
#endif
 
42
 
 
43
/**
 
44
 * @addtogroup libssh_session
 
45
 * @{
 
46
 */
 
47
 
 
48
/**
 
49
 * @brief Duplicate the options of a session structure.
 
50
 *
 
51
 * If you make several sessions with the same options this is useful. You
 
52
 * cannot use twice the same option structure in ssh_session_connect.
 
53
 *
 
54
 * @param src           The session to use to copy the options.
 
55
 *
 
56
 * @param dest          The session to copy the options to.
 
57
 *
 
58
 * @returns             0 on sucess, -1 on error with errno set.
 
59
 *
 
60
 * @see ssh_session_connect()
 
61
 */
 
62
int ssh_options_copy(ssh_session src, ssh_session *dest) {
 
63
  ssh_session new;
 
64
  int i;
 
65
 
 
66
  if (src == NULL || dest == NULL || *dest == NULL) {
 
67
    return -1;
 
68
  }
 
69
 
 
70
  new = *dest;
 
71
 
 
72
  if (src->username) {
 
73
    new->username = strdup(src->username);
 
74
    if (new->username == NULL) {
 
75
      return -1;
 
76
    }
 
77
  }
 
78
 
 
79
  if (src->host) {
 
80
    new->host = strdup(src->host);
 
81
    if (new->host == NULL) {
 
82
      return -1;
 
83
    }
 
84
  }
 
85
 
 
86
  if (src->identity) {
 
87
    struct ssh_iterator *it;
 
88
 
 
89
    new->identity = ssh_list_new();
 
90
    if (new->identity == NULL) {
 
91
      return -1;
 
92
    }
 
93
 
 
94
    it = ssh_list_get_iterator(src->identity);
 
95
    while (it) {
 
96
      char *id;
 
97
      int rc;
 
98
 
 
99
      id = strdup((char *) it->data);
 
100
      if (id == NULL) {
 
101
        return -1;
 
102
      }
 
103
 
 
104
      rc = ssh_list_append(new->identity, id);
 
105
      if (rc < 0) {
 
106
        return -1;
 
107
      }
 
108
      it = it->next;
 
109
    }
 
110
  }
 
111
 
 
112
  if (src->sshdir) {
 
113
    new->sshdir = strdup(src->sshdir);
 
114
    if (new->sshdir == NULL) {
 
115
      return -1;
 
116
    }
 
117
  }
 
118
 
 
119
  if (src->knownhosts) {
 
120
    new->knownhosts = strdup(src->knownhosts);
 
121
    if (new->knownhosts == NULL) {
 
122
      return -1;
 
123
    }
 
124
  }
 
125
 
 
126
  for (i = 0; i < 10; ++i) {
 
127
    if (src->wanted_methods[i]) {
 
128
      new->wanted_methods[i] = strdup(src->wanted_methods[i]);
 
129
      if (new->wanted_methods[i] == NULL) {
 
130
        return -1;
 
131
      }
 
132
    }
 
133
  }
 
134
 
 
135
  if(src->ProxyCommand) {
 
136
    new->ProxyCommand = strdup(src->ProxyCommand);
 
137
    if(new->ProxyCommand == NULL)
 
138
      return -1;
 
139
  }
 
140
  new->fd = src->fd;
 
141
  new->port = src->port;
 
142
  new->callbacks = src->callbacks;
 
143
  new->timeout = src->timeout;
 
144
  new->timeout_usec = src->timeout_usec;
 
145
  new->ssh2 = src->ssh2;
 
146
  new->ssh1 = src->ssh1;
 
147
  new->log_verbosity = src->log_verbosity;
 
148
  new->compressionlevel = src->compressionlevel;
 
149
 
 
150
  return 0;
 
151
}
 
152
 
 
153
int ssh_options_set_algo(ssh_session session, int algo,
 
154
    const char *list) {
 
155
  if (!verify_existing_algo(algo, list)) {
 
156
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
157
        "Setting method: no algorithm for method \"%s\" (%s)\n",
 
158
        ssh_kex_nums[algo], list);
 
159
    return -1;
 
160
  }
 
161
 
 
162
  SAFE_FREE(session->wanted_methods[algo]);
 
163
  session->wanted_methods[algo] = strdup(list);
 
164
  if (session->wanted_methods[algo] == NULL) {
 
165
    ssh_set_error_oom(session);
 
166
    return -1;
 
167
  }
 
168
 
 
169
  return 0;
 
170
}
 
171
 
 
172
/**
 
173
 * @brief This function can set all possible ssh options.
 
174
 *
 
175
 * @param  session An allocated SSH session structure.
 
176
 *
 
177
 * @param  type The option type to set. This could be one of the
 
178
 *              following:
 
179
 *
 
180
 *              - SSH_OPTIONS_HOST:
 
181
 *                The hostname or ip address to connect to (const char *).
 
182
 *
 
183
 *              - SSH_OPTIONS_PORT:
 
184
 *                The port to connect to (unsigned int).
 
185
 *
 
186
 *              - SSH_OPTIONS_PORT_STR:
 
187
 *                The port to connect to (const char *).
 
188
 *
 
189
 *              - SSH_OPTIONS_FD:
 
190
 *                The file descriptor to use (socket_t).\n
 
191
 *                \n
 
192
 *                If you wish to open the socket yourself for a reason
 
193
 *                or another, set the file descriptor. Don't forget to
 
194
 *                set the hostname as the hostname is used as a key in
 
195
 *                the known_host mechanism.
 
196
 *
 
197
 *              - SSH_OPTIONS_BINDADDR:
 
198
 *                The address to bind the client to (const char *).
 
199
 *
 
200
 *              - SSH_OPTIONS_USER:
 
201
 *                The username for authentication (const char *).\n
 
202
 *                \n
 
203
 *                If the value is NULL, the username is set to the
 
204
 *                default username.
 
205
 *
 
206
 *              - SSH_OPTIONS_SSH_DIR:
 
207
 *                Set the ssh directory (const char *,format string).\n
 
208
 *                \n
 
209
 *                If the value is NULL, the directory is set to the
 
210
 *                default ssh directory.\n
 
211
 *                \n
 
212
 *                The ssh directory is used for files like known_hosts
 
213
 *                and identity (private and public key). It may include
 
214
 *                "%s" which will be replaced by the user home
 
215
 *                directory.
 
216
 *
 
217
 *              - SSH_OPTIONS_KNOWNHOSTS:
 
218
 *                Set the known hosts file name (const char *,format string).\n
 
219
 *                \n
 
220
 *                If the value is NULL, the directory is set to the
 
221
 *                default known hosts file, normally
 
222
 *                ~/.ssh/known_hosts.\n
 
223
 *                \n
 
224
 *                The known hosts file is used to certify remote hosts
 
225
 *                are genuine. It may include "%s" which will be
 
226
 *                replaced by the user home directory.
 
227
 *
 
228
 *              - SSH_OPTIONS_IDENTITY:
 
229
 *                Set the identity file name (const char *,format string).\n
 
230
 *                \n
 
231
 *                By default identity, id_dsa and id_rsa are checked.\n
 
232
 *                \n
 
233
 *                The identity file used authenticate with public key.
 
234
 *                It may include "%s" which will be replaced by the
 
235
 *                user home directory.
 
236
 *
 
237
 *              - SSH_OPTIONS_TIMEOUT:
 
238
 *                Set a timeout for the connection in seconds (long).
 
239
 *
 
240
 *              - SSH_OPTIONS_TIMEOUT_USEC:
 
241
 *                Set a timeout for the connection in micro seconds
 
242
 *                        (long).
 
243
 *
 
244
 *              - SSH_OPTIONS_SSH1:
 
245
 *                Allow or deny the connection to SSH1 servers
 
246
 *                (int, 0 is false).
 
247
 *
 
248
 *              - SSH_OPTIONS_SSH2:
 
249
 *                Allow or deny the connection to SSH2 servers
 
250
 *                (int, 0 is false).
 
251
 *
 
252
 *              - SSH_OPTIONS_LOG_VERBOSITY:
 
253
 *                Set the session logging verbosity (int).\n
 
254
 *                \n
 
255
 *                The verbosity of the messages. Every log smaller or
 
256
 *                equal to verbosity will be shown.
 
257
 *                - SSH_LOG_NOLOG: No logging
 
258
 *                - SSH_LOG_RARE: Rare conditions or warnings
 
259
 *                - SSH_LOG_ENTRY: API-accessible entrypoints
 
260
 *                - SSH_LOG_PACKET: Packet id and size
 
261
 *                - SSH_LOG_FUNCTIONS: Function entering and leaving
 
262
 *
 
263
 *              - SSH_OPTIONS_LOG_VERBOSITY_STR:
 
264
 *                Set the session logging verbosity (const char *).\n
 
265
 *                \n
 
266
 *                The verbosity of the messages. Every log smaller or
 
267
 *                equal to verbosity will be shown.
 
268
 *                - SSH_LOG_NOLOG: No logging
 
269
 *                - SSH_LOG_RARE: Rare conditions or warnings
 
270
 *                - SSH_LOG_ENTRY: API-accessible entrypoints
 
271
 *                - SSH_LOG_PACKET: Packet id and size
 
272
 *                - SSH_LOG_FUNCTIONS: Function entering and leaving
 
273
 *                \n
 
274
 *                See the corresponding numbers in libssh.h.
 
275
 *
 
276
 *              - SSH_OPTIONS_AUTH_CALLBACK:
 
277
 *                Set a callback to use your own authentication function
 
278
 *                (function pointer).
 
279
 *
 
280
 *              - SSH_OPTIONS_AUTH_USERDATA:
 
281
 *                Set the user data passed to the authentication
 
282
 *                function (generic pointer).
 
283
 *
 
284
 *              - SSH_OPTIONS_LOG_CALLBACK:
 
285
 *                Set a callback to use your own logging function
 
286
 *                (function pointer).
 
287
 *
 
288
 *              - SSH_OPTIONS_LOG_USERDATA:
 
289
 *                Set the user data passed to the logging function
 
290
 *                (generic pointer).
 
291
 *
 
292
 *              - SSH_OPTIONS_STATUS_CALLBACK:
 
293
 *                Set a callback to show connection status in realtime
 
294
 *                (function pointer).\n
 
295
 *                \n
 
296
 *                @code
 
297
 *                fn(void *arg, float status)
 
298
 *                @endcode
 
299
 *                \n
 
300
 *                During ssh_connect(), libssh will call the callback
 
301
 *                with status from 0.0 to 1.0.
 
302
 *
 
303
 *              - SSH_OPTIONS_STATUS_ARG:
 
304
 *                Set the status argument which should be passed to the
 
305
 *                status callback (generic pointer).
 
306
 *
 
307
 *              - SSH_OPTIONS_CIPHERS_C_S:
 
308
 *                Set the symmetric cipher client to server (const char *,
 
309
 *                comma-separated list).
 
310
 *
 
311
 *              - SSH_OPTIONS_CIPHERS_S_C:
 
312
 *                Set the symmetric cipher server to client (const char *,
 
313
 *                comma-separated list).
 
314
 *
 
315
 *              - SSH_OPTIONS_COMPRESSION_C_S:
 
316
 *                Set the compression to use for client to server
 
317
 *                communication (const char *, "yes", "no" or a specific
 
318
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
 
319
 *
 
320
 *              - SSH_OPTIONS_COMPRESSION_S_C:
 
321
 *                Set the compression to use for server to client
 
322
 *                communication (const char *, "yes", "no" or a specific
 
323
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
 
324
 *
 
325
 *              - SSH_OPTIONS_COMPRESSION:
 
326
 *                Set the compression to use for both directions
 
327
 *                communication (const char *, "yes", "no" or a specific
 
328
 *                algorithm name if needed ("zlib","zlib@openssh.com","none").
 
329
 *
 
330
 *              - SSH_OPTIONS_COMPRESSION_LEVEL:
 
331
 *                Set the compression level to use for zlib functions. (int,
 
332
 *                value from 1 to 9, 9 being the most efficient but slower).
 
333
 *
 
334
 *              - SSH_OPTIONS_STRICTHOSTKEYCHECK:
 
335
 *                Set the parameter StrictHostKeyChecking to avoid
 
336
 *                asking about a fingerprint (int, 0 = false).
 
337
 *
 
338
 *              - SSH_OPTIONS_PROXYCOMMAND:
 
339
 *                Set the command to be executed in order to connect to
 
340
 *                server (const char *).
 
341
 *
 
342
 * @param  value The value to set. This is a generic pointer and the
 
343
 *               datatype which is used should be set according to the
 
344
 *               type set.
 
345
 *
 
346
 * @return       0 on success, < 0 on error.
 
347
 */
 
348
int ssh_options_set(ssh_session session, enum ssh_options_e type,
 
349
    const void *value) {
 
350
  char *p, *q;
 
351
  long int i;
 
352
  int rc;
 
353
 
 
354
  if (session == NULL) {
 
355
    return -1;
 
356
  }
 
357
 
 
358
  switch (type) {
 
359
    case SSH_OPTIONS_HOST:
 
360
      q = strdup(value);
 
361
      if (q == NULL) {
 
362
        ssh_set_error_oom(session);
 
363
        return -1;
 
364
      }
 
365
      p = strchr(q, '@');
 
366
 
 
367
      SAFE_FREE(session->host);
 
368
 
 
369
      if (p) {
 
370
        *p = '\0';
 
371
        session->host = strdup(p + 1);
 
372
        if (session->host == NULL) {
 
373
          SAFE_FREE(q);
 
374
          ssh_set_error_oom(session);
 
375
          return -1;
 
376
        }
 
377
 
 
378
        SAFE_FREE(session->username);
 
379
        session->username = strdup(q);
 
380
        SAFE_FREE(q);
 
381
        if (session->username == NULL) {
 
382
          ssh_set_error_oom(session);
 
383
          return -1;
 
384
        }
 
385
      } else {
 
386
        session->host = q;
 
387
      }
 
388
      break;
 
389
    case SSH_OPTIONS_PORT:
 
390
      if (value == NULL) {
 
391
        session->port = 22 & 0xffff;
 
392
      } else {
 
393
        int *x = (int *) value;
 
394
 
 
395
        session->port = *x & 0xffff;
 
396
      }
 
397
      break;
 
398
    case SSH_OPTIONS_PORT_STR:
 
399
      if (value == NULL) {
 
400
        session->port = 22 & 0xffff;
 
401
      } else {
 
402
        q = strdup(value);
 
403
        if (q == NULL) {
 
404
          ssh_set_error_oom(session);
 
405
          return -1;
 
406
        }
 
407
        i = strtol(q, &p, 10);
 
408
        if (q == p) {
 
409
          SAFE_FREE(q);
 
410
        }
 
411
        SAFE_FREE(q);
 
412
 
 
413
        session->port = i & 0xffff;
 
414
      }
 
415
      break;
 
416
    case SSH_OPTIONS_FD:
 
417
      if (value == NULL) {
 
418
        session->fd = SSH_INVALID_SOCKET;
 
419
      } else {
 
420
        socket_t *x = (socket_t *) value;
 
421
 
 
422
        session->fd = *x & 0xffff;
 
423
      }
 
424
      break;
 
425
    case SSH_OPTIONS_BINDADDR:
 
426
      if (value == NULL) {
 
427
        ssh_set_error_invalid(session, __FUNCTION__);
 
428
        return -1;
 
429
      }
 
430
      q = strdup(value);
 
431
      if (q == NULL) {
 
432
          return -1;
 
433
      }
 
434
      SAFE_FREE(session->bindaddr);
 
435
      session->bindaddr = q;
 
436
      break;
 
437
    case SSH_OPTIONS_USER:
 
438
      SAFE_FREE(session->username);
 
439
      if (value == NULL) { /* set default username */
 
440
        q = ssh_get_local_username(session);
 
441
        if (q == NULL) {
 
442
          return -1;
 
443
        }
 
444
        session->username = q;
 
445
      } else { /* username provided */
 
446
        session->username = strdup(value);
 
447
        if (session->username == NULL) {
 
448
          ssh_set_error_oom(session);
 
449
          return -1;
 
450
        }
 
451
      }
 
452
      break;
 
453
    case SSH_OPTIONS_SSH_DIR:
 
454
      if (value == NULL) {
 
455
        SAFE_FREE(session->sshdir);
 
456
 
 
457
        session->sshdir = ssh_path_expand_tilde("~/.ssh");
 
458
        if (session->sshdir == NULL) {
 
459
          return -1;
 
460
        }
 
461
      } else {
 
462
        SAFE_FREE(session->sshdir);
 
463
        session->sshdir = ssh_path_expand_tilde(value);
 
464
        if (session->sshdir == NULL) {
 
465
          return -1;
 
466
        }
 
467
      }
 
468
      break;
 
469
    case SSH_OPTIONS_IDENTITY:
 
470
    case SSH_OPTIONS_ADD_IDENTITY:
 
471
      if (value == NULL) {
 
472
        ssh_set_error_invalid(session, __FUNCTION__);
 
473
        return -1;
 
474
      }
 
475
      q = strdup(value);
 
476
      if (q == NULL) {
 
477
          return -1;
 
478
      }
 
479
      rc = ssh_list_prepend(session->identity, q);
 
480
      if (rc < 0) {
 
481
        return -1;
 
482
      }
 
483
      break;
 
484
    case SSH_OPTIONS_KNOWNHOSTS:
 
485
      if (value == NULL) {
 
486
        SAFE_FREE(session->knownhosts);
 
487
        if (session->sshdir == NULL) {
 
488
            return -1;
 
489
        }
 
490
        session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts");
 
491
        if (session->knownhosts == NULL) {
 
492
          return -1;
 
493
        }
 
494
      } else {
 
495
        SAFE_FREE(session->knownhosts);
 
496
        session->knownhosts = strdup(value);
 
497
        if (session->knownhosts == NULL) {
 
498
          return -1;
 
499
        }
 
500
      }
 
501
      break;
 
502
    case SSH_OPTIONS_TIMEOUT:
 
503
      if (value == NULL) {
 
504
        ssh_set_error_invalid(session, __FUNCTION__);
 
505
        return -1;
 
506
      } else {
 
507
        long *x = (long *) value;
 
508
 
 
509
        session->timeout = *x & 0xffffffff;
 
510
      }
 
511
      break;
 
512
    case SSH_OPTIONS_TIMEOUT_USEC:
 
513
      if (value == NULL) {
 
514
        ssh_set_error_invalid(session, __FUNCTION__);
 
515
        return -1;
 
516
      } else {
 
517
        long *x = (long *) value;
 
518
 
 
519
        session->timeout_usec = *x & 0xffffffff;
 
520
      }
 
521
      break;
 
522
    case SSH_OPTIONS_SSH1:
 
523
      if (value == NULL) {
 
524
        ssh_set_error_invalid(session, __FUNCTION__);
 
525
        return -1;
 
526
      } else {
 
527
        int *x = (int *) value;
 
528
        session->ssh1 = *x;
 
529
      }
 
530
      break;
 
531
    case SSH_OPTIONS_SSH2:
 
532
      if (value == NULL) {
 
533
        ssh_set_error_invalid(session, __FUNCTION__);
 
534
        return -1;
 
535
      } else {
 
536
        int *x = (int *) value;
 
537
        session->ssh2 = *x & 0xffff;
 
538
      }
 
539
      break;
 
540
    case SSH_OPTIONS_LOG_VERBOSITY:
 
541
      if (value == NULL) {
 
542
        ssh_set_error_invalid(session, __FUNCTION__);
 
543
        return -1;
 
544
      } else {
 
545
        int *x = (int *) value;
 
546
 
 
547
        session->log_verbosity = *x & 0xffff;
 
548
      }
 
549
      break;
 
550
    case SSH_OPTIONS_LOG_VERBOSITY_STR:
 
551
      if (value == NULL) {
 
552
        session->log_verbosity = 0 & 0xffff;
 
553
      } else {
 
554
        q = strdup(value);
 
555
        if (q == NULL) {
 
556
          ssh_set_error_oom(session);
 
557
          return -1;
 
558
        }
 
559
        i = strtol(q, &p, 10);
 
560
        if (q == p) {
 
561
          SAFE_FREE(q);
 
562
        }
 
563
        SAFE_FREE(q);
 
564
 
 
565
        session->log_verbosity = i & 0xffff;
 
566
      }
 
567
      break;
 
568
    case SSH_OPTIONS_CIPHERS_C_S:
 
569
      if (value == NULL) {
 
570
        ssh_set_error_invalid(session, __FUNCTION__);
 
571
        return -1;
 
572
      } else {
 
573
        if (ssh_options_set_algo(session, SSH_CRYPT_C_S, value) < 0)
 
574
          return -1;
 
575
      }
 
576
      break;
 
577
    case SSH_OPTIONS_CIPHERS_S_C:
 
578
      if (value == NULL) {
 
579
        ssh_set_error_invalid(session, __FUNCTION__);
 
580
        return -1;
 
581
      } else {
 
582
        if (ssh_options_set_algo(session, SSH_CRYPT_S_C, value) < 0)
 
583
          return -1;
 
584
      }
 
585
      break;
 
586
    case SSH_OPTIONS_COMPRESSION_C_S:
 
587
      if (value == NULL) {
 
588
        ssh_set_error_invalid(session, __FUNCTION__);
 
589
        return -1;
 
590
      } else {
 
591
        if (strcasecmp(value,"yes")==0){
 
592
          if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,zlib") < 0)
 
593
            return -1;
 
594
        } else if (strcasecmp(value,"no")==0){
 
595
          if(ssh_options_set_algo(session,SSH_COMP_C_S,"none") < 0)
 
596
            return -1;
 
597
        } else {
 
598
          if (ssh_options_set_algo(session, SSH_COMP_C_S, value) < 0)
 
599
            return -1;
 
600
        }
 
601
      }
 
602
      break;
 
603
    case SSH_OPTIONS_COMPRESSION_S_C:
 
604
      if (value == NULL) {
 
605
        ssh_set_error_invalid(session, __FUNCTION__);
 
606
        return -1;
 
607
      } else {
 
608
        if (strcasecmp(value,"yes")==0){
 
609
          if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,zlib") < 0)
 
610
            return -1;
 
611
        } else if (strcasecmp(value,"no")==0){
 
612
          if(ssh_options_set_algo(session,SSH_COMP_S_C,"none") < 0)
 
613
            return -1;
 
614
        } else {
 
615
          if (ssh_options_set_algo(session, SSH_COMP_S_C, value) < 0)
 
616
            return -1;
 
617
        }
 
618
      }
 
619
      break;
 
620
    case SSH_OPTIONS_COMPRESSION:
 
621
      if (value==NULL) {
 
622
        ssh_set_error_invalid(session, __FUNCTION__);
 
623
        return -1;
 
624
      }
 
625
      if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_C_S,value) < 0)
 
626
        return -1;
 
627
      if(ssh_options_set(session,SSH_OPTIONS_COMPRESSION_S_C,value) < 0)
 
628
        return -1;
 
629
      break;
 
630
    case SSH_OPTIONS_COMPRESSION_LEVEL:
 
631
      if (value==NULL) {
 
632
        ssh_set_error_invalid(session, __FUNCTION__);
 
633
        return -1;
 
634
      }
 
635
      else {
 
636
        int *x=(int *)value;
 
637
        if(*x < 1 || *x > 9){
 
638
          ssh_set_error_invalid(session, __FUNCTION__);
 
639
          return -1;
 
640
        }
 
641
        session->compressionlevel=*x & 0xff;
 
642
      }
 
643
      break;
 
644
    case SSH_OPTIONS_STRICTHOSTKEYCHECK:
 
645
      if (value == NULL) {
 
646
        ssh_set_error_invalid(session, __FUNCTION__);
 
647
        return -1;
 
648
      } else {
 
649
        session->StrictHostKeyChecking = *(int*)value;
 
650
      }
 
651
      break;
 
652
    case SSH_OPTIONS_PROXYCOMMAND:
 
653
      if (value == NULL) {
 
654
        ssh_set_error_invalid(session, __FUNCTION__);
 
655
        return -1;
 
656
      } else {
 
657
        SAFE_FREE(session->ProxyCommand);
 
658
        q = strdup(value);
 
659
        if (q == NULL) {
 
660
            return -1;
 
661
        }
 
662
        session->ProxyCommand = q;
 
663
      }
 
664
      break;
 
665
    default:
 
666
      ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
 
667
      return -1;
 
668
    break;
 
669
  }
 
670
 
 
671
  return 0;
 
672
}
 
673
 
 
674
 
 
675
/**
 
676
 * @brief Parse command line arguments.
 
677
 *
 
678
 * This is a helper for your application to generate the appropriate
 
679
 * options from the command line arguments.\n
 
680
 * The argv array and argc value are changed so that the parsed
 
681
 * arguments wont appear anymore in them.\n
 
682
 * The single arguments (without switches) are not parsed. thus,
 
683
 * myssh -l user localhost\n
 
684
 * The command wont set the hostname value of options to localhost.
 
685
 *
 
686
 * @param session       The session to configure.
 
687
 *
 
688
 * @param argcptr       The pointer to the argument count.
 
689
 *
 
690
 * @param argv          The arguments list pointer.
 
691
 *
 
692
 * @returns 0 on success, < 0 on error.
 
693
 *
 
694
 * @see ssh_session_new()
 
695
 */
 
696
int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
 
697
  char *user = NULL;
 
698
  char *cipher = NULL;
 
699
  char *identity = NULL;
 
700
  char *port = NULL;
 
701
  char **save = NULL;
 
702
  int i = 0;
 
703
  int argc = *argcptr;
 
704
  int debuglevel = 0;
 
705
  int usersa = 0;
 
706
  int usedss = 0;
 
707
  int compress = 0;
 
708
  int cont = 1;
 
709
  int current = 0;
 
710
#ifdef WITH_SSH1
 
711
  int ssh1 = 1;
 
712
#else
 
713
  int ssh1 = 0;
 
714
#endif
 
715
  int ssh2 = 1;
 
716
#ifdef _MSC_VER
 
717
    /* Not supported with a Microsoft compiler */
 
718
    return -1;
 
719
#else
 
720
  int saveoptind = optind; /* need to save 'em */
 
721
  int saveopterr = opterr;
 
722
 
 
723
  save = malloc(argc * sizeof(char *));
 
724
  if (save == NULL) {
 
725
    ssh_set_error_oom(session);
 
726
    return -1;
 
727
  }
 
728
 
 
729
  opterr = 0; /* shut up getopt */
 
730
  while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
 
731
    switch(i) {
 
732
      case 'l':
 
733
        user = optarg;
 
734
        break;
 
735
      case 'p':
 
736
        port = optarg;
 
737
        break;
 
738
      case 'v':
 
739
        debuglevel++;
 
740
        break;
 
741
      case 'r':
 
742
        usersa++;
 
743
        break;
 
744
      case 'd':
 
745
        usedss++;
 
746
        break;
 
747
      case 'c':
 
748
        cipher = optarg;
 
749
        break;
 
750
      case 'i':
 
751
        identity = optarg;
 
752
        break;
 
753
      case 'C':
 
754
        compress++;
 
755
        break;
 
756
      case '2':
 
757
        ssh2 = 1;
 
758
        ssh1 = 0;
 
759
        break;
 
760
      case '1':
 
761
        ssh2 = 0;
 
762
        ssh1 = 1;
 
763
        break;
 
764
      default:
 
765
        {
 
766
          char opt[3]="- ";
 
767
          opt[1] = optopt;
 
768
          save[current] = strdup(opt);
 
769
          if (save[current] == NULL) {
 
770
            SAFE_FREE(save);
 
771
            ssh_set_error_oom(session);
 
772
            return -1;
 
773
          }
 
774
          current++;
 
775
          if (optarg) {
 
776
            save[current++] = argv[optind + 1];
 
777
          }
 
778
        }
 
779
    } /* switch */
 
780
  } /* while */
 
781
  opterr = saveopterr;
 
782
  while (optind < argc) {
 
783
    save[current++] = argv[optind++];
 
784
  }
 
785
 
 
786
  if (usersa && usedss) {
 
787
    ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
 
788
    cont = 0;
 
789
  }
 
790
 
 
791
  ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &debuglevel);
 
792
 
 
793
  optind = saveoptind;
 
794
 
 
795
  if(!cont) {
 
796
    SAFE_FREE(save);
 
797
    return -1;
 
798
  }
 
799
 
 
800
  /* first recopy the save vector into the original's */
 
801
  for (i = 0; i < current; i++) {
 
802
    /* don't erase argv[0] */
 
803
    argv[ i + 1] = save[i];
 
804
  }
 
805
  argv[current + 1] = NULL;
 
806
  *argcptr = current + 1;
 
807
  SAFE_FREE(save);
 
808
 
 
809
  /* set a new option struct */
 
810
  if (compress) {
 
811
    if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
 
812
      cont = 0;
 
813
    }
 
814
  }
 
815
 
 
816
  if (cont && cipher) {
 
817
    if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) {
 
818
      cont = 0;
 
819
    }
 
820
    if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) {
 
821
      cont = 0;
 
822
    }
 
823
  }
 
824
 
 
825
  if (cont && user) {
 
826
    if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
 
827
      cont = 0;
 
828
    }
 
829
  }
 
830
 
 
831
  if (cont && identity) {
 
832
    if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) {
 
833
      cont = 0;
 
834
    }
 
835
  }
 
836
 
 
837
  ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
 
838
 
 
839
  ssh_options_set(session, SSH_OPTIONS_SSH1, &ssh1);
 
840
  ssh_options_set(session, SSH_OPTIONS_SSH2, &ssh2);
 
841
 
 
842
  if (!cont) {
 
843
    return SSH_ERROR;
 
844
  }
 
845
 
 
846
  return SSH_OK;
 
847
#endif
 
848
}
 
849
 
 
850
/**
 
851
 * @brief Parse the ssh config file.
 
852
 *
 
853
 * This should be the last call of all options, it may overwrite options which
 
854
 * are already set. It requires that the host name is already set with
 
855
 * ssh_options_set_host().
 
856
 *
 
857
 * @param  session      SSH session handle
 
858
 *
 
859
 * @param  filename     The options file to use, if NULL the default
 
860
 *                      ~/.ssh/config will be used.
 
861
 *
 
862
 * @return 0 on success, < 0 on error.
 
863
 *
 
864
 * @see ssh_options_set_host()
 
865
 */
 
866
int ssh_options_parse_config(ssh_session session, const char *filename) {
 
867
  char *expanded_filename;
 
868
  int r;
 
869
 
 
870
  if (session == NULL) {
 
871
    return -1;
 
872
  }
 
873
  if (session->host == NULL) {
 
874
    ssh_set_error_invalid(session, __FUNCTION__);
 
875
    return -1;
 
876
  }
 
877
 
 
878
  if (session->sshdir == NULL) {
 
879
      r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
 
880
      if (r < 0) {
 
881
          ssh_set_error_oom(session);
 
882
          return -1;
 
883
      }
 
884
  }
 
885
 
 
886
  /* set default filename */
 
887
  if (filename == NULL) {
 
888
    expanded_filename = ssh_path_expand_escape(session, "%d/config");
 
889
  } else {
 
890
    expanded_filename = ssh_path_expand_escape(session, filename);
 
891
  }
 
892
  if (expanded_filename == NULL) {
 
893
    return -1;
 
894
  }
 
895
 
 
896
  r = ssh_config_parse_file(session, expanded_filename);
 
897
  if (r < 0) {
 
898
      goto out;
 
899
  }
 
900
  if (filename == NULL) {
 
901
      r = ssh_config_parse_file(session, "/etc/ssh/ssh_config");
 
902
  }
 
903
 
 
904
out:
 
905
  free(expanded_filename);
 
906
  return r;
 
907
}
 
908
 
 
909
int ssh_options_apply(ssh_session session) {
 
910
    struct ssh_iterator *it;
 
911
    char *tmp;
 
912
    int rc;
 
913
 
 
914
    if (session->sshdir == NULL) {
 
915
        rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
 
916
        if (rc < 0) {
 
917
            return -1;
 
918
        }
 
919
    }
 
920
 
 
921
    if (session->username == NULL) {
 
922
        rc = ssh_options_set(session, SSH_OPTIONS_USER, NULL);
 
923
        if (rc < 0) {
 
924
            return -1;
 
925
        }
 
926
    }
 
927
 
 
928
    if (session->knownhosts == NULL) {
 
929
        tmp = ssh_path_expand_escape(session, "%d/known_hosts");
 
930
    } else {
 
931
        tmp = ssh_path_expand_escape(session, session->knownhosts);
 
932
    }
 
933
    if (tmp == NULL) {
 
934
        return -1;
 
935
    }
 
936
    free(session->knownhosts);
 
937
    session->knownhosts = tmp;
 
938
 
 
939
    if (session->ProxyCommand != NULL) {
 
940
        tmp = ssh_path_expand_escape(session, session->ProxyCommand);
 
941
        if (tmp == NULL) {
 
942
            return -1;
 
943
        }
 
944
        free(session->ProxyCommand);
 
945
        session->ProxyCommand = tmp;
 
946
    }
 
947
 
 
948
    for (it = ssh_list_get_iterator(session->identity);
 
949
         it != NULL;
 
950
         it = it->next) {
 
951
        char *id = (char *) it->data;
 
952
        tmp = ssh_path_expand_escape(session, id);
 
953
        if (tmp == NULL) {
 
954
            return -1;
 
955
        }
 
956
        free(id);
 
957
        it->data = tmp;
 
958
    }
 
959
 
 
960
    return 0;
 
961
}
 
962
 
 
963
/** @} */
 
964
 
 
965
#ifdef WITH_SERVER
 
966
/**
 
967
 * @addtogroup libssh_server
 
968
 * @{
 
969
 */
 
970
static int ssh_bind_options_set_algo(ssh_bind sshbind, int algo,
 
971
    const char *list) {
 
972
  if (!verify_existing_algo(algo, list)) {
 
973
    ssh_set_error(sshbind, SSH_REQUEST_DENIED,
 
974
        "Setting method: no algorithm for method \"%s\" (%s)\n",
 
975
        ssh_kex_nums[algo], list);
 
976
    return -1;
 
977
  }
 
978
 
 
979
  SAFE_FREE(sshbind->wanted_methods[algo]);
 
980
  sshbind->wanted_methods[algo] = strdup(list);
 
981
  if (sshbind->wanted_methods[algo] == NULL) {
 
982
    ssh_set_error_oom(sshbind);
 
983
    return -1;
 
984
  }
 
985
 
 
986
  return 0;
 
987
}
 
988
 
 
989
/**
 
990
 * @brief This function can set all possible ssh bind options.
 
991
 *
 
992
 * @param  session      An allocated ssh option structure.
 
993
 *
 
994
 * @param  type         The option type to set. This could be one of the
 
995
 *                      following:
 
996
 *
 
997
 *                      SSH_BIND_OPTIONS_LOG_VERBOSITY:
 
998
 *                        Set the session logging verbosity (integer).
 
999
 *
 
1000
 *                        The verbosity of the messages. Every log smaller or
 
1001
 *                        equal to verbosity will be shown.
 
1002
 *                          SSH_LOG_NOLOG: No logging
 
1003
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
1004
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
1005
 *                          SSH_LOG_PACKET: Packet id and size
 
1006
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
1007
 *
 
1008
 *                      SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
 
1009
 *                        Set the session logging verbosity (integer).
 
1010
 *
 
1011
 *                        The verbosity of the messages. Every log smaller or
 
1012
 *                        equal to verbosity will be shown.
 
1013
 *                          SSH_LOG_NOLOG: No logging
 
1014
 *                          SSH_LOG_RARE: Rare conditions or warnings
 
1015
 *                          SSH_LOG_ENTRY: API-accessible entrypoints
 
1016
 *                          SSH_LOG_PACKET: Packet id and size
 
1017
 *                          SSH_LOG_FUNCTIONS: Function entering and leaving
 
1018
 *
 
1019
 *                      SSH_BIND_OPTIONS_BINDADDR:
 
1020
 *                        Set the bind address.
 
1021
 *
 
1022
 *                      SSH_BIND_OPTIONS_BINDPORT:
 
1023
 *                        Set the bind port, default is 22.
 
1024
 *
 
1025
 *                      SSH_BIND_OPTIONS_HOSTKEY:
 
1026
 *                        Set the server public key type: ssh-rsa or ssh-dss
 
1027
 *                        (string).
 
1028
 *
 
1029
 *                      SSH_BIND_OPTIONS_DSAKEY:
 
1030
 *                        Set the path to the dsa ssh host key (string).
 
1031
 *
 
1032
 *                      SSH_BIND_OPTIONS_RSAKEY:
 
1033
 *                        Set the path to the ssh host rsa key (string).
 
1034
 *
 
1035
 *                      SSH_BIND_OPTIONS_BANNER:
 
1036
 *                        Set the server banner sent to clients (string).
 
1037
 *
 
1038
 * @param  value        The value to set. This is a generic pointer and the
 
1039
 *                      datatype which is used should be set according to the
 
1040
 *                      type set.
 
1041
 *
 
1042
 * @return              0 on success, < 0 on error.
 
1043
 */
 
1044
int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
 
1045
    const void *value) {
 
1046
  char *p, *q;
 
1047
  int i;
 
1048
 
 
1049
  if (sshbind == NULL) {
 
1050
    return -1;
 
1051
  }
 
1052
 
 
1053
  switch (type) {
 
1054
    case SSH_BIND_OPTIONS_HOSTKEY:
 
1055
      if (value == NULL) {
 
1056
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1057
        return -1;
 
1058
      } else {
 
1059
        if (ssh_bind_options_set_algo(sshbind, SSH_HOSTKEYS, value) < 0)
 
1060
          return -1;
 
1061
      }
 
1062
      break;
 
1063
    case SSH_BIND_OPTIONS_BINDADDR:
 
1064
      if (value == NULL) {
 
1065
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1066
        return -1;
 
1067
      } else {
 
1068
        SAFE_FREE(sshbind->bindaddr);
 
1069
        sshbind->bindaddr = strdup(value);
 
1070
        if (sshbind->bindaddr == NULL) {
 
1071
          ssh_set_error_oom(sshbind);
 
1072
          return -1;
 
1073
        }
 
1074
      }
 
1075
      break;
 
1076
    case SSH_BIND_OPTIONS_BINDPORT:
 
1077
      if (value == NULL) {
 
1078
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1079
        return -1;
 
1080
      } else {
 
1081
        int *x = (int *) value;
 
1082
        sshbind->bindport = *x & 0xffff;
 
1083
      }
 
1084
      break;
 
1085
    case SSH_BIND_OPTIONS_BINDPORT_STR:
 
1086
      if (value == NULL) {
 
1087
        sshbind->bindport = 22 & 0xffff;
 
1088
      } else {
 
1089
        q = strdup(value);
 
1090
        if (q == NULL) {
 
1091
          ssh_set_error_oom(sshbind);
 
1092
          return -1;
 
1093
        }
 
1094
        i = strtol(q, &p, 10);
 
1095
        if (q == p) {
 
1096
          SAFE_FREE(q);
 
1097
        }
 
1098
        SAFE_FREE(q);
 
1099
 
 
1100
        sshbind->bindport = i & 0xffff;
 
1101
      }
 
1102
      break;
 
1103
    case SSH_BIND_OPTIONS_LOG_VERBOSITY:
 
1104
      if (value == NULL) {
 
1105
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1106
        return -1;
 
1107
      } else {
 
1108
        int *x = (int *) value;
 
1109
        sshbind->log_verbosity = *x & 0xffff;
 
1110
      }
 
1111
      break;
 
1112
    case SSH_BIND_OPTIONS_LOG_VERBOSITY_STR:
 
1113
      if (value == NULL) {
 
1114
        sshbind->log_verbosity = 0;
 
1115
      } else {
 
1116
        q = strdup(value);
 
1117
        if (q == NULL) {
 
1118
          ssh_set_error_oom(sshbind);
 
1119
          return -1;
 
1120
        }
 
1121
        i = strtol(q, &p, 10);
 
1122
        if (q == p) {
 
1123
          SAFE_FREE(q);
 
1124
        }
 
1125
        SAFE_FREE(q);
 
1126
 
 
1127
        sshbind->log_verbosity = i & 0xffff;
 
1128
      }
 
1129
      break;
 
1130
    case SSH_BIND_OPTIONS_DSAKEY:
 
1131
      if (value == NULL) {
 
1132
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1133
        return -1;
 
1134
      } else {
 
1135
        SAFE_FREE(sshbind->dsakey);
 
1136
        sshbind->dsakey = strdup(value);
 
1137
        if (sshbind->dsakey == NULL) {
 
1138
          ssh_set_error_oom(sshbind);
 
1139
          return -1;
 
1140
        }
 
1141
      }
 
1142
      break;
 
1143
    case SSH_BIND_OPTIONS_RSAKEY:
 
1144
      if (value == NULL) {
 
1145
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1146
        return -1;
 
1147
      } else {
 
1148
        SAFE_FREE(sshbind->rsakey);
 
1149
        sshbind->rsakey = strdup(value);
 
1150
        if (sshbind->rsakey == NULL) {
 
1151
          ssh_set_error_oom(sshbind);
 
1152
          return -1;
 
1153
        }
 
1154
      }
 
1155
      break;
 
1156
    case SSH_BIND_OPTIONS_BANNER:
 
1157
      if (value == NULL) {
 
1158
        ssh_set_error_invalid(sshbind, __FUNCTION__);
 
1159
        return -1;
 
1160
      } else {
 
1161
        SAFE_FREE(sshbind->banner);
 
1162
        sshbind->banner = strdup(value);
 
1163
        if (sshbind->banner == NULL) {
 
1164
          ssh_set_error_oom(sshbind);
 
1165
          return -1;
 
1166
        }
 
1167
      }
 
1168
      break;
 
1169
    default:
 
1170
      ssh_set_error(sshbind, SSH_REQUEST_DENIED, "Unknown ssh option %d", type);
 
1171
      return -1;
 
1172
    break;
 
1173
  }
 
1174
 
 
1175
  return 0;
 
1176
}
 
1177
#endif
 
1178
 
 
1179
/** @} */
 
1180
 
 
1181
/* vim: set ts=4 sw=4 et cindent: */