~ubuntu-branches/ubuntu/quantal/libssh/quantal-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2012-4561.patch/src/keyfiles.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-11-22 13:34:54 UTC
  • Revision ID: package-import@ubuntu.com-20121122133454-dx5fq7yrdhqpv7ad
Tags: 0.5.2-1ubuntu0.12.10.1
* SECURITY UPDATE: denial of service and possible code execution via
  multiple double free flaws
  - debian/patches/CVE-2012-4559.patch: properly do frees in src/agent.c,
    src/channels.c, src/sftp.c.
  - CVE-2012-4559
* SECURITY UPDATE: denial of service and possible code execution via
  multiple buffer overflows
  - debian/patches/CVE-2012-4560.patch: properly calculate sizes in
    src/misc.c.
  - CVE-2012-4560
* SECURITY UPDATE: denial of service and possible code execution via
  multiple invalid free flaws
  - debian/patches/CVE-2012-4561.patch: don't use after free in
    src/keyfiles.c, properly zero structs in src/keys.c.
  - CVE-2012-4561
* SECURITY UPDATE: denial of service and possible code execution via
  multiple improper overflow checks
  - debian/patches/CVE-2012-4562.patch: do proper overflow checks in
    src/buffer.c, src/dh.c, src/string.c.
  - CVE-2012-4562

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * keyfiles.c - private and public key handling for authentication.
 
3
 *
 
4
 * This file is part of the SSH Library
 
5
 *
 
6
 * Copyright (c) 2003-2009 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
 
 
27
#include <errno.h>
 
28
#include <fcntl.h>
 
29
#include <sys/stat.h>
 
30
#include <sys/types.h>
 
31
#include <stdio.h>
 
32
#include <string.h>
 
33
#include <stdlib.h>
 
34
 
 
35
#ifdef _WIN32
 
36
# if _MSC_VER >= 1400
 
37
#  include <io.h>
 
38
#  undef open
 
39
#  define open _open
 
40
#  undef close
 
41
#  define close _close
 
42
#  undef read
 
43
#  define read _read
 
44
#  undef unlink
 
45
#  define unlink _unlink
 
46
# endif /* _MSC_VER */
 
47
#else
 
48
# include <arpa/inet.h>
 
49
#endif
 
50
 
 
51
#include "libssh/priv.h"
 
52
#include "libssh/buffer.h"
 
53
#include "libssh/keyfiles.h"
 
54
#include "libssh/session.h"
 
55
#include "libssh/wrapper.h"
 
56
#include "libssh/misc.h"
 
57
#include "libssh/keys.h"
 
58
 
 
59
/*todo: remove this include */
 
60
#include "libssh/string.h"
 
61
 
 
62
 
 
63
#ifdef HAVE_LIBGCRYPT
 
64
#include <gcrypt.h>
 
65
#elif defined HAVE_LIBCRYPTO
 
66
#include <openssl/pem.h>
 
67
#include <openssl/dsa.h>
 
68
#include <openssl/err.h>
 
69
#include <openssl/rsa.h>
 
70
#endif /* HAVE_LIBCRYPTO */
 
71
 
 
72
#define MAXLINESIZE 80
 
73
#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
 
74
#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
 
75
#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
 
76
#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
 
77
 
 
78
#ifdef HAVE_LIBGCRYPT
 
79
 
 
80
#define MAX_KEY_SIZE 32
 
81
#define MAX_PASSPHRASE_SIZE 1024
 
82
#define ASN1_INTEGER 2
 
83
#define ASN1_SEQUENCE 48
 
84
#define PKCS5_SALT_LEN 8
 
85
 
 
86
static int load_iv(char *header, unsigned char *iv, int iv_len) {
 
87
  int i;
 
88
  int j;
 
89
  int k;
 
90
 
 
91
  memset(iv, 0, iv_len);
 
92
  for (i = 0; i < iv_len; i++) {
 
93
    if ((header[2*i] >= '0') && (header[2*i] <= '9'))
 
94
      j = header[2*i] - '0';
 
95
    else if ((header[2*i] >= 'A') && (header[2*i] <= 'F'))
 
96
      j = header[2*i] - 'A' + 10;
 
97
    else if ((header[2*i] >= 'a') && (header[2*i] <= 'f'))
 
98
      j = header[2*i] - 'a' + 10;
 
99
    else
 
100
      return -1;
 
101
    if ((header[2*i+1] >= '0') && (header[2*i+1] <= '9'))
 
102
      k = header[2*i+1] - '0';
 
103
    else if ((header[2*i+1] >= 'A') && (header[2*i+1] <= 'F'))
 
104
      k = header[2*i+1] - 'A' + 10;
 
105
    else if ((header[2*i+1] >= 'a') && (header[2*i+1] <= 'f'))
 
106
      k = header[2*i+1] - 'a' + 10;
 
107
    else
 
108
      return -1;
 
109
    iv[i] = (j << 4) + k;
 
110
  }
 
111
  return 0;
 
112
}
 
113
 
 
114
static uint32_t char_to_u32(unsigned char *data, uint32_t size) {
 
115
  uint32_t ret;
 
116
  uint32_t i;
 
117
 
 
118
  for (i = 0, ret = 0; i < size; ret = ret << 8, ret += data[i++])
 
119
    ;
 
120
  return ret;
 
121
}
 
122
 
 
123
static uint32_t asn1_get_len(ssh_buffer buffer) {
 
124
  uint32_t len;
 
125
  unsigned char tmp[4];
 
126
 
 
127
  if (buffer_get_data(buffer,tmp,1) == 0) {
 
128
    return 0;
 
129
  }
 
130
 
 
131
  if (tmp[0] > 127) {
 
132
    len = tmp[0] & 127;
 
133
    if (len > 4) {
 
134
      return 0; /* Length doesn't fit in u32. Can this really happen? */
 
135
    }
 
136
    if (buffer_get_data(buffer,tmp,len) == 0) {
 
137
      return 0;
 
138
    }
 
139
    len = char_to_u32(tmp, len);
 
140
  } else {
 
141
    len = char_to_u32(tmp, 1);
 
142
  }
 
143
 
 
144
  return len;
 
145
}
 
146
 
 
147
static ssh_string asn1_get_int(ssh_buffer buffer) {
 
148
  ssh_string str;
 
149
  unsigned char type;
 
150
  uint32_t size;
 
151
 
 
152
  if (buffer_get_data(buffer, &type, 1) == 0 || type != ASN1_INTEGER) {
 
153
    return NULL;
 
154
  }
 
155
  size = asn1_get_len(buffer);
 
156
  if (size == 0) {
 
157
    return NULL;
 
158
  }
 
159
 
 
160
  str = ssh_string_new(size);
 
161
  if (str == NULL) {
 
162
    return NULL;
 
163
  }
 
164
 
 
165
  if (buffer_get_data(buffer, str->string, size) == 0) {
 
166
    ssh_string_free(str);
 
167
    return NULL;
 
168
  }
 
169
 
 
170
  return str;
 
171
}
 
172
 
 
173
static int asn1_check_sequence(ssh_buffer buffer) {
 
174
  unsigned char *j = NULL;
 
175
  unsigned char tmp;
 
176
  int i;
 
177
  uint32_t size;
 
178
  uint32_t padding;
 
179
 
 
180
  if (buffer_get_data(buffer, &tmp, 1) == 0 || tmp != ASN1_SEQUENCE) {
 
181
    return 0;
 
182
  }
 
183
 
 
184
  size = asn1_get_len(buffer);
 
185
  if ((padding = ssh_buffer_get_len(buffer) - buffer->pos - size) > 0) {
 
186
    for (i = ssh_buffer_get_len(buffer) - buffer->pos - size,
 
187
         j = (unsigned char*)ssh_buffer_get_begin(buffer) + size + buffer->pos;
 
188
         i;
 
189
         i--, j++)
 
190
    {
 
191
      if (*j != padding) {                   /* padding is allowed */
 
192
        return 0;                            /* but nothing else */
 
193
      }
 
194
    }
 
195
  }
 
196
 
 
197
  return 1;
 
198
}
 
199
 
 
200
static int read_line(char *data, unsigned int len, FILE *fp) {
 
201
  char tmp;
 
202
  unsigned int i;
 
203
 
 
204
  for (i = 0; fread(&tmp, 1, 1, fp) && tmp != '\n' && i < len; data[i++] = tmp)
 
205
    ;
 
206
  if (tmp == '\n') {
 
207
    return i;
 
208
  }
 
209
 
 
210
  if (i >= len) {
 
211
    return -1;
 
212
  }
 
213
 
 
214
  return 0;
 
215
}
 
216
 
 
217
static int passphrase_to_key(char *data, unsigned int datalen,
 
218
    unsigned char *salt, unsigned char *key, unsigned int keylen) {
 
219
  MD5CTX md;
 
220
  unsigned char digest[MD5_DIGEST_LEN] = {0};
 
221
  unsigned int i;
 
222
  unsigned int j;
 
223
  unsigned int md_not_empty;
 
224
 
 
225
  for (j = 0, md_not_empty = 0; j < keylen; ) {
 
226
    md = md5_init();
 
227
    if (md == NULL) {
 
228
      return -1;
 
229
    }
 
230
 
 
231
    if (md_not_empty) {
 
232
      md5_update(md, digest, MD5_DIGEST_LEN);
 
233
    } else {
 
234
      md_not_empty = 1;
 
235
    }
 
236
 
 
237
    md5_update(md, data, datalen);
 
238
    if (salt) {
 
239
      md5_update(md, salt, PKCS5_SALT_LEN);
 
240
    }
 
241
    md5_final(digest, md);
 
242
 
 
243
    for (i = 0; j < keylen && i < MD5_DIGEST_LEN; j++, i++) {
 
244
      if (key) {
 
245
        key[j] = digest[i];
 
246
      }
 
247
    }
 
248
  }
 
249
 
 
250
  return 0;
 
251
}
 
252
 
 
253
static int privatekey_decrypt(int algo, int mode, unsigned int key_len,
 
254
                       unsigned char *iv, unsigned int iv_len,
 
255
                       ssh_buffer data, ssh_auth_callback cb,
 
256
                       void *userdata,
 
257
                       const char *desc)
 
258
{
 
259
  char passphrase[MAX_PASSPHRASE_SIZE] = {0};
 
260
  unsigned char key[MAX_KEY_SIZE] = {0};
 
261
  unsigned char *tmp = NULL;
 
262
  gcry_cipher_hd_t cipher;
 
263
  int rc = -1;
 
264
 
 
265
  if (!algo) {
 
266
    return -1;
 
267
  }
 
268
 
 
269
  if (cb) {
 
270
    rc = (*cb)(desc, passphrase, MAX_PASSPHRASE_SIZE, 0, 0, userdata);
 
271
    if (rc < 0) {
 
272
      return -1;
 
273
    }
 
274
  } else if (cb == NULL && userdata != NULL) {
 
275
    snprintf(passphrase, MAX_PASSPHRASE_SIZE, "%s", (char *) userdata);
 
276
  }
 
277
 
 
278
  if (passphrase_to_key(passphrase, strlen(passphrase), iv, key, key_len) < 0) {
 
279
    return -1;
 
280
  }
 
281
 
 
282
  if (gcry_cipher_open(&cipher, algo, mode, 0)
 
283
      || gcry_cipher_setkey(cipher, key, key_len)
 
284
      || gcry_cipher_setiv(cipher, iv, iv_len)
 
285
      || (tmp = malloc(ssh_buffer_get_len(data) * sizeof (char))) == NULL
 
286
      || gcry_cipher_decrypt(cipher, tmp, ssh_buffer_get_len(data),
 
287
                       ssh_buffer_get_begin(data), ssh_buffer_get_len(data))) {
 
288
    gcry_cipher_close(cipher);
 
289
    return -1;
 
290
  }
 
291
 
 
292
  memcpy(ssh_buffer_get_begin(data), tmp, ssh_buffer_get_len(data));
 
293
 
 
294
  SAFE_FREE(tmp);
 
295
  gcry_cipher_close(cipher);
 
296
 
 
297
  return 0;
 
298
}
 
299
 
 
300
static int privatekey_dek_header(char *header, unsigned int header_len,
 
301
    int *algo, int *mode, unsigned int *key_len, unsigned char **iv,
 
302
    unsigned int *iv_len) {
 
303
  unsigned int iv_pos;
 
304
 
 
305
  if (header_len > 13 && !strncmp("DES-EDE3-CBC", header, 12))
 
306
  {
 
307
    *algo = GCRY_CIPHER_3DES;
 
308
    iv_pos = 13;
 
309
    *mode = GCRY_CIPHER_MODE_CBC;
 
310
    *key_len = 24;
 
311
    *iv_len = 8;
 
312
  }
 
313
  else if (header_len > 8 && !strncmp("DES-CBC", header, 7))
 
314
  {
 
315
    *algo = GCRY_CIPHER_DES;
 
316
    iv_pos = 8;
 
317
    *mode = GCRY_CIPHER_MODE_CBC;
 
318
    *key_len = 8;
 
319
    *iv_len = 8;
 
320
  }
 
321
  else if (header_len > 12 && !strncmp("AES-128-CBC", header, 11))
 
322
  {
 
323
    *algo = GCRY_CIPHER_AES128;
 
324
    iv_pos = 12;
 
325
    *mode = GCRY_CIPHER_MODE_CBC;
 
326
    *key_len = 16;
 
327
    *iv_len = 16;
 
328
  }
 
329
  else if (header_len > 12 && !strncmp("AES-192-CBC", header, 11))
 
330
  {
 
331
    *algo = GCRY_CIPHER_AES192;
 
332
    iv_pos = 12;
 
333
    *mode = GCRY_CIPHER_MODE_CBC;
 
334
    *key_len = 24;
 
335
    *iv_len = 16;
 
336
  }
 
337
  else if (header_len > 12 && !strncmp("AES-256-CBC", header, 11))
 
338
  {
 
339
    *algo = GCRY_CIPHER_AES256;
 
340
    iv_pos = 12;
 
341
    *mode = GCRY_CIPHER_MODE_CBC;
 
342
    *key_len = 32;
 
343
    *iv_len = 16;
 
344
  } else {
 
345
    return -1;
 
346
  }
 
347
 
 
348
  *iv = malloc(*iv_len);
 
349
  if (*iv == NULL) {
 
350
    return -1;
 
351
  }
 
352
 
 
353
  return load_iv(header + iv_pos, *iv, *iv_len);
 
354
}
 
355
 
 
356
static ssh_buffer privatekey_file_to_buffer(FILE *fp, int type,
 
357
    ssh_auth_callback cb, void *userdata, const char *desc) {
 
358
  ssh_buffer buffer = NULL;
 
359
  ssh_buffer out = NULL;
 
360
  char buf[MAXLINESIZE] = {0};
 
361
  unsigned char *iv = NULL;
 
362
  const char *header_begin;
 
363
  const char *header_end;
 
364
  unsigned int header_begin_size;
 
365
  unsigned int header_end_size;
 
366
  unsigned int key_len = 0;
 
367
  unsigned int iv_len = 0;
 
368
  int algo = 0;
 
369
  int mode = 0;
 
370
  int len;
 
371
 
 
372
  buffer = ssh_buffer_new();
 
373
  if (buffer == NULL) {
 
374
    return NULL;
 
375
  }
 
376
 
 
377
  switch(type) {
 
378
    case SSH_KEYTYPE_DSS:
 
379
      header_begin = DSA_HEADER_BEGIN;
 
380
      header_end = DSA_HEADER_END;
 
381
      break;
 
382
    case SSH_KEYTYPE_RSA:
 
383
      header_begin = RSA_HEADER_BEGIN;
 
384
      header_end = RSA_HEADER_END;
 
385
      break;
 
386
    default:
 
387
      ssh_buffer_free(buffer);
 
388
      return NULL;
 
389
  }
 
390
 
 
391
  header_begin_size = strlen(header_begin);
 
392
  header_end_size = strlen(header_end);
 
393
 
 
394
  while (read_line(buf, MAXLINESIZE, fp) &&
 
395
      strncmp(buf, header_begin, header_begin_size))
 
396
    ;
 
397
 
 
398
  len = read_line(buf, MAXLINESIZE, fp);
 
399
  if (len > 11 && strncmp("Proc-Type: 4,ENCRYPTED", buf, 11) == 0) {
 
400
    len = read_line(buf, MAXLINESIZE, fp);
 
401
    if (len > 10 && strncmp("DEK-Info: ", buf, 10) == 0) {
 
402
      if ((privatekey_dek_header(buf + 10, len - 10, &algo, &mode, &key_len,
 
403
                                 &iv, &iv_len) < 0)
 
404
          || read_line(buf, MAXLINESIZE, fp)) {
 
405
        ssh_buffer_free(buffer);
 
406
        SAFE_FREE(iv);
 
407
        return NULL;
 
408
      }
 
409
    } else {
 
410
      ssh_buffer_free(buffer);
 
411
      SAFE_FREE(iv);
 
412
      return NULL;
 
413
    }
 
414
  } else {
 
415
    if (buffer_add_data(buffer, buf, len) < 0) {
 
416
      ssh_buffer_free(buffer);
 
417
      SAFE_FREE(iv);
 
418
      return NULL;
 
419
    }
 
420
  }
 
421
 
 
422
  while ((len = read_line(buf,MAXLINESIZE,fp)) &&
 
423
      strncmp(buf, header_end, header_end_size) != 0) {
 
424
    if (len == -1) {
 
425
      ssh_buffer_free(buffer);
 
426
      SAFE_FREE(iv);
 
427
      return NULL;
 
428
    }
 
429
    if (buffer_add_data(buffer, buf, len) < 0) {
 
430
      ssh_buffer_free(buffer);
 
431
      SAFE_FREE(iv);
 
432
      return NULL;
 
433
    }
 
434
  }
 
435
 
 
436
  if (strncmp(buf,header_end,header_end_size) != 0) {
 
437
    ssh_buffer_free(buffer);
 
438
    SAFE_FREE(iv);
 
439
    return NULL;
 
440
  }
 
441
 
 
442
  if (buffer_add_data(buffer, "\0", 1) < 0) {
 
443
    ssh_buffer_free(buffer);
 
444
    SAFE_FREE(iv);
 
445
    return NULL;
 
446
  }
 
447
 
 
448
  out = base64_to_bin(ssh_buffer_get_begin(buffer));
 
449
  ssh_buffer_free(buffer);
 
450
  if (out == NULL) {
 
451
    SAFE_FREE(iv);
 
452
    return NULL;
 
453
  }
 
454
 
 
455
  if (algo) {
 
456
    if (privatekey_decrypt(algo, mode, key_len, iv, iv_len, out,
 
457
          cb, userdata, desc) < 0) {
 
458
      ssh_buffer_free(out);
 
459
      SAFE_FREE(iv);
 
460
      return NULL;
 
461
    }
 
462
  }
 
463
  SAFE_FREE(iv);
 
464
 
 
465
  return out;
 
466
}
 
467
 
 
468
static int read_rsa_privatekey(FILE *fp, gcry_sexp_t *r,
 
469
    ssh_auth_callback cb, void *userdata, const char *desc) {
 
470
  ssh_string n = NULL;
 
471
  ssh_string e = NULL;
 
472
  ssh_string d = NULL;
 
473
  ssh_string p = NULL;
 
474
  ssh_string q = NULL;
 
475
  ssh_string unused1 = NULL;
 
476
  ssh_string unused2 = NULL;
 
477
  ssh_string u = NULL;
 
478
  ssh_string v = NULL;
 
479
  ssh_buffer buffer = NULL;
 
480
  int rc = 1;
 
481
 
 
482
  buffer = privatekey_file_to_buffer(fp, SSH_KEYTYPE_RSA, cb, userdata, desc);
 
483
  if (buffer == NULL) {
 
484
    return 0;
 
485
  }
 
486
 
 
487
  if (!asn1_check_sequence(buffer)) {
 
488
    ssh_buffer_free(buffer);
 
489
    return 0;
 
490
  }
 
491
 
 
492
  v = asn1_get_int(buffer);
 
493
  if (ntohl(v->size) != 1 || v->string[0] != 0) {
 
494
    ssh_buffer_free(buffer);
 
495
    return 0;
 
496
  }
 
497
 
 
498
  n = asn1_get_int(buffer);
 
499
  e = asn1_get_int(buffer);
 
500
  d = asn1_get_int(buffer);
 
501
  q = asn1_get_int(buffer);
 
502
  p = asn1_get_int(buffer);
 
503
  unused1 = asn1_get_int(buffer);
 
504
  unused2 = asn1_get_int(buffer);
 
505
  u = asn1_get_int(buffer);
 
506
 
 
507
  ssh_buffer_free(buffer);
 
508
 
 
509
  if (n == NULL || e == NULL || d == NULL || p == NULL || q == NULL ||
 
510
      unused1 == NULL || unused2 == NULL|| u == NULL) {
 
511
    rc = 0;
 
512
    goto error;
 
513
  }
 
514
 
 
515
  if (gcry_sexp_build(r, NULL,
 
516
      "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
 
517
      ntohl(n->size), n->string,
 
518
      ntohl(e->size), e->string,
 
519
      ntohl(d->size), d->string,
 
520
      ntohl(p->size), p->string,
 
521
      ntohl(q->size), q->string,
 
522
      ntohl(u->size), u->string)) {
 
523
    rc = 0;
 
524
  }
 
525
 
 
526
error:
 
527
  ssh_string_free(n);
 
528
  ssh_string_free(e);
 
529
  ssh_string_free(d);
 
530
  ssh_string_free(p);
 
531
  ssh_string_free(q);
 
532
  ssh_string_free(unused1);
 
533
  ssh_string_free(unused2);
 
534
  ssh_string_free(u);
 
535
  ssh_string_free(v);
 
536
 
 
537
  return rc;
 
538
}
 
539
 
 
540
static int read_dsa_privatekey(FILE *fp, gcry_sexp_t *r, ssh_auth_callback cb,
 
541
    void *userdata, const char *desc) {
 
542
  ssh_buffer buffer = NULL;
 
543
  ssh_string p = NULL;
 
544
  ssh_string q = NULL;
 
545
  ssh_string g = NULL;
 
546
  ssh_string y = NULL;
 
547
  ssh_string x = NULL;
 
548
  ssh_string v = NULL;
 
549
  int rc = 1;
 
550
 
 
551
  buffer = privatekey_file_to_buffer(fp, SSH_KEYTYPE_DSS, cb, userdata, desc);
 
552
  if (buffer == NULL) {
 
553
    return 0;
 
554
  }
 
555
 
 
556
  if (!asn1_check_sequence(buffer)) {
 
557
    ssh_buffer_free(buffer);
 
558
    return 0;
 
559
  }
 
560
 
 
561
  v = asn1_get_int(buffer);
 
562
  if (ntohl(v->size) != 1 || v->string[0] != 0) {
 
563
    ssh_buffer_free(buffer);
 
564
    return 0;
 
565
  }
 
566
 
 
567
  p = asn1_get_int(buffer);
 
568
  q = asn1_get_int(buffer);
 
569
  g = asn1_get_int(buffer);
 
570
  y = asn1_get_int(buffer);
 
571
  x = asn1_get_int(buffer);
 
572
  ssh_buffer_free(buffer);
 
573
 
 
574
  if (p == NULL || q == NULL || g == NULL || y == NULL || x == NULL) {
 
575
    rc = 0;
 
576
    goto error;
 
577
  }
 
578
 
 
579
  if (gcry_sexp_build(r, NULL,
 
580
        "(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",
 
581
        ntohl(p->size), p->string,
 
582
        ntohl(q->size), q->string,
 
583
        ntohl(g->size), g->string,
 
584
        ntohl(y->size), y->string,
 
585
        ntohl(x->size), x->string)) {
 
586
    rc = 0;
 
587
  }
 
588
 
 
589
error:
 
590
  ssh_string_free(p);
 
591
  ssh_string_free(q);
 
592
  ssh_string_free(g);
 
593
  ssh_string_free(y);
 
594
  ssh_string_free(x);
 
595
  ssh_string_free(v);
 
596
 
 
597
  return rc;
 
598
}
 
599
#endif /* HAVE_LIBGCRYPT */
 
600
 
 
601
#ifdef HAVE_LIBCRYPTO
 
602
static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
 
603
  ssh_session session = userdata;
 
604
 
 
605
  /* unused flag */
 
606
  (void) rwflag;
 
607
  if(buf==NULL)
 
608
    return 0;
 
609
  memset(buf,'\0',size);
 
610
  ssh_log(session, SSH_LOG_RARE,
 
611
      "Trying to call external authentication function");
 
612
 
 
613
  if (session && session->callbacks && session->callbacks->auth_function) {
 
614
    if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
 
615
        session->callbacks->userdata) < 0) {
 
616
      return 0;
 
617
    }
 
618
 
 
619
    return strlen(buf);
 
620
  }
 
621
 
 
622
  return 0;
 
623
}
 
624
#endif /* HAVE_LIBCRYPTO */
 
625
 
 
626
static int privatekey_type_from_file(FILE *fp) {
 
627
  char buffer[MAXLINESIZE] = {0};
 
628
 
 
629
  if (!fgets(buffer, MAXLINESIZE, fp)) {
 
630
    return 0;
 
631
  }
 
632
  fseek(fp, 0, SEEK_SET);
 
633
  if (strncmp(buffer, DSA_HEADER_BEGIN, strlen(DSA_HEADER_BEGIN)) == 0) {
 
634
    return SSH_KEYTYPE_DSS;
 
635
  }
 
636
  if (strncmp(buffer, RSA_HEADER_BEGIN, strlen(RSA_HEADER_BEGIN)) == 0) {
 
637
    return SSH_KEYTYPE_RSA;
 
638
  }
 
639
  return 0;
 
640
}
 
641
 
 
642
/**
 
643
 * @addtogroup libssh_auth
 
644
 *
 
645
 * @{
 
646
 */
 
647
 
 
648
/**
 
649
 * @brief Reads a SSH private key from a file.
 
650
 *
 
651
 * @param[in] session  The SSH Session to use.
 
652
 *
 
653
 * @param[in] filename The filename of the the private key.
 
654
 *
 
655
 * @param[in] type     The type of the private key. This could be SSH_KEYTYPE_DSS or
 
656
 *                     SSH_KEYTYPE_RSA. Pass 0 to automatically detect the type.
 
657
 *
 
658
 * @param[in] passphrase The passphrase to decrypt the private key. Set to null
 
659
 *                       if none is needed or it is unknown.
 
660
 *
 
661
 * @return              A private_key object containing the private key, or
 
662
 *                       NULL on error.
 
663
 * @see privatekey_free()
 
664
 * @see publickey_from_privatekey()
 
665
 */
 
666
ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
 
667
    int type, const char *passphrase) {
 
668
  ssh_private_key privkey = NULL;
 
669
  FILE *file = NULL;
 
670
#ifdef HAVE_LIBGCRYPT
 
671
  ssh_auth_callback auth_cb = NULL;
 
672
  void *auth_ud = NULL;
 
673
 
 
674
  gcry_sexp_t dsa = NULL;
 
675
  gcry_sexp_t rsa = NULL;
 
676
  int valid;
 
677
#elif defined HAVE_LIBCRYPTO
 
678
  DSA *dsa = NULL;
 
679
  RSA *rsa = NULL;
 
680
  BIO *bio = NULL;
 
681
#endif
 
682
  /* TODO Implement to read both DSA and RSA at once. */
 
683
 
 
684
  /* needed for openssl initialization */
 
685
  if (ssh_init() < 0) {
 
686
    return NULL;
 
687
  }
 
688
 
 
689
  ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
 
690
  file = fopen(filename,"r");
 
691
  if (file == NULL) {
 
692
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
693
        "Error opening %s: %s", filename, strerror(errno));
 
694
    return NULL;
 
695
  }
 
696
 
 
697
#ifdef HAVE_LIBCRYPTO
 
698
  bio = BIO_new_file(filename,"r");
 
699
  if (bio == NULL) {
 
700
          fclose(file);
 
701
      ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
 
702
      return NULL;
 
703
  }
 
704
#endif
 
705
 
 
706
  ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
 
707
      filename, passphrase ? "true" : "false",
 
708
      session->callbacks && session->callbacks->auth_function ? "true" : "false");
 
709
 
 
710
  if (type == 0) {
 
711
    type = privatekey_type_from_file(file);
 
712
    if (type == 0) {
 
713
      fclose(file);
 
714
      ssh_set_error(session, SSH_FATAL, "Invalid private key file.");
 
715
      return NULL;
 
716
    }
 
717
  }
 
718
  switch (type) {
 
719
    case SSH_KEYTYPE_DSS:
 
720
      if (passphrase == NULL) {
 
721
#ifdef HAVE_LIBGCRYPT
 
722
        if (session->callbacks && session->callbacks->auth_function) {
 
723
          auth_cb = session->callbacks->auth_function;
 
724
          auth_ud = session->callbacks->userdata;
 
725
 
 
726
          valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
 
727
              "Passphrase for private key:");
 
728
        } else { /* authcb */
 
729
          valid = read_dsa_privatekey(file, &dsa, NULL, NULL, NULL);
 
730
        } /* authcb */
 
731
      } else { /* passphrase */
 
732
        valid = read_dsa_privatekey(file, &dsa, NULL,
 
733
            (void *) passphrase, NULL);
 
734
      }
 
735
 
 
736
      fclose(file);
 
737
 
 
738
      if (!valid) {
 
739
        ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
 
740
#elif defined HAVE_LIBCRYPTO
 
741
        if (session->callbacks && session->callbacks->auth_function) {
 
742
          dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, pem_get_password, session);
 
743
        } else { /* authcb */
 
744
          /* openssl uses its own callback to get the passphrase here */
 
745
          dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
 
746
        } /* authcb */
 
747
      } else { /* passphrase */
 
748
        dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
 
749
      }
 
750
 
 
751
          BIO_free(bio);
 
752
      fclose(file);
 
753
      if (dsa == NULL) {
 
754
        ssh_set_error(session, SSH_FATAL,
 
755
            "Parsing private key %s: %s",
 
756
            filename, ERR_error_string(ERR_get_error(), NULL));
 
757
#endif
 
758
        return NULL;
 
759
      }
 
760
      break;
 
761
    case SSH_KEYTYPE_RSA:
 
762
      if (passphrase == NULL) {
 
763
#ifdef HAVE_LIBGCRYPT
 
764
        if (session->callbacks && session->callbacks->auth_function) {
 
765
          auth_cb = session->callbacks->auth_function;
 
766
          auth_ud = session->callbacks->userdata;
 
767
          valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
 
768
              "Passphrase for private key:");
 
769
        } else { /* authcb */
 
770
          valid = read_rsa_privatekey(file, &rsa, NULL, NULL, NULL);
 
771
        } /* authcb */
 
772
      } else { /* passphrase */
 
773
        valid = read_rsa_privatekey(file, &rsa, NULL,
 
774
            (void *) passphrase, NULL);
 
775
      }
 
776
 
 
777
      fclose(file);
 
778
 
 
779
      if (!valid) {
 
780
        ssh_set_error(session,SSH_FATAL, "Parsing private key %s", filename);
 
781
#elif defined HAVE_LIBCRYPTO
 
782
        if (session->callbacks && session->callbacks->auth_function) {
 
783
                        rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, pem_get_password, session);
 
784
        } else { /* authcb */
 
785
          /* openssl uses its own callback to get the passphrase here */
 
786
          rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
 
787
        } /* authcb */
 
788
      } else { /* passphrase */
 
789
        rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, (void *) passphrase);
 
790
      }
 
791
 
 
792
          BIO_free(bio);
 
793
      fclose(file);
 
794
 
 
795
      if (rsa == NULL) {
 
796
        ssh_set_error(session, SSH_FATAL,
 
797
            "Parsing private key %s: %s",
 
798
            filename, ERR_error_string(ERR_get_error(),NULL));
 
799
#endif
 
800
        return NULL;
 
801
      }
 
802
      break;
 
803
    default:
 
804
#ifdef HAVE_LIBCRYPTO
 
805
          BIO_free(bio);
 
806
#endif
 
807
      fclose(file);
 
808
      ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
 
809
      return NULL;
 
810
  } /* switch */
 
811
 
 
812
  privkey = malloc(sizeof(struct ssh_private_key_struct));
 
813
  if (privkey == NULL) {
 
814
#ifdef HAVE_LIBGCRYPT
 
815
    gcry_sexp_release(dsa);
 
816
    gcry_sexp_release(rsa);
 
817
#elif defined HAVE_LIBCRYPTO
 
818
    DSA_free(dsa);
 
819
    RSA_free(rsa);
 
820
#endif
 
821
    return NULL;
 
822
  }
 
823
  ZERO_STRUCTP(privkey);
 
824
  privkey->type = type;
 
825
  privkey->dsa_priv = dsa;
 
826
  privkey->rsa_priv = rsa;
 
827
 
 
828
  return privkey;
 
829
}
 
830
 
 
831
/**
 
832
 * @brief returns the type of a private key
 
833
 * @param[in] privatekey the private key handle
 
834
 * @returns one of SSH_KEYTYPE_RSA,SSH_KEYTYPE_DSS,SSH_KEYTYPE_RSA1
 
835
 * @returns SSH_KEYTYPE_UNKNOWN if the type is unknown
 
836
 * @see privatekey_from_file
 
837
 * @see ssh_userauth_offer_pubkey
 
838
 */
 
839
enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey){
 
840
  if (privatekey==NULL)
 
841
    return SSH_KEYTYPE_UNKNOWN;
 
842
  return privatekey->type;
 
843
}
 
844
 
 
845
/* same that privatekey_from_file() but without any passphrase things. */
 
846
ssh_private_key _privatekey_from_file(void *session, const char *filename,
 
847
    int type) {
 
848
  ssh_private_key privkey = NULL;
 
849
#ifdef HAVE_LIBGCRYPT
 
850
  FILE *file = NULL;
 
851
  gcry_sexp_t dsa = NULL;
 
852
  gcry_sexp_t rsa = NULL;
 
853
  int valid;
 
854
#elif defined HAVE_LIBCRYPTO
 
855
  DSA *dsa = NULL;
 
856
  RSA *rsa = NULL;
 
857
  BIO *bio = NULL;
 
858
#endif
 
859
 
 
860
#ifdef HAVE_LIBGCRYPT
 
861
  file = fopen(filename,"r");
 
862
  if (file == NULL) {
 
863
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
864
        "Error opening %s: %s", filename, strerror(errno));
 
865
    return NULL;
 
866
  }
 
867
#elif defined HAVE_LIBCRYPTO
 
868
  bio = BIO_new_file(filename,"r");
 
869
  if (bio == NULL) {
 
870
      ssh_set_error(session, SSH_FATAL, "Could not create BIO.");
 
871
      return NULL;
 
872
  }
 
873
#endif
 
874
 
 
875
  switch (type) {
 
876
    case SSH_KEYTYPE_DSS:
 
877
#ifdef HAVE_LIBGCRYPT
 
878
      valid = read_dsa_privatekey(file, &dsa, NULL, NULL, NULL);
 
879
 
 
880
      fclose(file);
 
881
 
 
882
      if (!valid) {
 
883
        ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
 
884
#elif defined HAVE_LIBCRYPTO
 
885
      dsa = PEM_read_bio_DSAPrivateKey(bio, NULL, NULL, NULL);
 
886
 
 
887
      BIO_free(bio);
 
888
 
 
889
      if (dsa == NULL) {
 
890
        ssh_set_error(session, SSH_FATAL,
 
891
            "Parsing private key %s: %s",
 
892
            filename, ERR_error_string(ERR_get_error(), NULL));
 
893
#else
 
894
      {
 
895
#endif
 
896
        return NULL;
 
897
      }
 
898
      break;
 
899
    case SSH_KEYTYPE_RSA:
 
900
#ifdef HAVE_LIBGCRYPT
 
901
      valid = read_rsa_privatekey(file, &rsa, NULL, NULL, NULL);
 
902
 
 
903
      fclose(file);
 
904
 
 
905
      if (!valid) {
 
906
        ssh_set_error(session, SSH_FATAL, "Parsing private key %s", filename);
 
907
#elif defined HAVE_LIBCRYPTO
 
908
      rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
 
909
 
 
910
      BIO_free(bio);
 
911
 
 
912
      if (rsa == NULL) {
 
913
        ssh_set_error(session, SSH_FATAL,
 
914
            "Parsing private key %s: %s",
 
915
            filename, ERR_error_string(ERR_get_error(), NULL));
 
916
#else
 
917
      {
 
918
#endif
 
919
        return NULL;
 
920
      }
 
921
      break;
 
922
    default:
 
923
#ifdef HAVE_LIBGCRYPT
 
924
        fclose(file);
 
925
#elif defined HAVE_LIBCRYPTO
 
926
        BIO_free(bio);
 
927
#endif
 
928
        ssh_set_error(session, SSH_FATAL, "Invalid private key type %d", type);
 
929
        return NULL;
 
930
  }
 
931
 
 
932
  privkey = malloc(sizeof(struct ssh_private_key_struct));
 
933
  if (privkey == NULL) {
 
934
#ifdef HAVE_LIBGCRYPT
 
935
    gcry_sexp_release(dsa);
 
936
    gcry_sexp_release(rsa);
 
937
#elif defined HAVE_LIBCRYPTO
 
938
    DSA_free(dsa);
 
939
    RSA_free(rsa);
 
940
#endif
 
941
    return NULL;
 
942
  }
 
943
 
 
944
  privkey->type = type;
 
945
  privkey->dsa_priv = dsa;
 
946
  privkey->rsa_priv = rsa;
 
947
 
 
948
  return privkey;
 
949
}
 
950
 
 
951
/**
 
952
 * @brief Deallocate a private key object.
 
953
 *
 
954
 * @param[in]  prv      The private_key object to free.
 
955
 */
 
956
void privatekey_free(ssh_private_key prv) {
 
957
  if (prv == NULL) {
 
958
    return;
 
959
  }
 
960
 
 
961
#ifdef HAVE_LIBGCRYPT
 
962
  gcry_sexp_release(prv->dsa_priv);
 
963
  gcry_sexp_release(prv->rsa_priv);
 
964
#elif defined HAVE_LIBCRYPTO
 
965
  DSA_free(prv->dsa_priv);
 
966
  RSA_free(prv->rsa_priv);
 
967
#endif
 
968
  memset(prv, 0, sizeof(struct ssh_private_key_struct));
 
969
  SAFE_FREE(prv);
 
970
}
 
971
 
 
972
/**
 
973
 * @brief Write a public key to a file.
 
974
 *
 
975
 * @param[in]  session  The ssh session to use.
 
976
 *
 
977
 * @param[in]  file     The filename to write the key into.
 
978
 *
 
979
 * @param[in]  pubkey   The public key to write.
 
980
 *
 
981
 * @param[in]  type     The type of the public key.
 
982
 *
 
983
 * @return              0 on success, -1 on error.
 
984
 */
 
985
int ssh_publickey_to_file(ssh_session session, const char *file,
 
986
    ssh_string pubkey, int type) {
 
987
  FILE *fp;
 
988
  char *user;
 
989
  char buffer[1024];
 
990
  char host[256];
 
991
  unsigned char *pubkey_64;
 
992
  size_t len;
 
993
  int rc;
 
994
  if(session==NULL)
 
995
        return SSH_ERROR;
 
996
  if(file==NULL || pubkey==NULL){
 
997
        ssh_set_error(session, SSH_FATAL, "Invalid parameters");
 
998
        return SSH_ERROR;
 
999
  }
 
1000
  pubkey_64 = bin_to_base64(pubkey->string, ssh_string_len(pubkey));
 
1001
  if (pubkey_64 == NULL) {
 
1002
    return SSH_ERROR;
 
1003
  }
 
1004
 
 
1005
  user = ssh_get_local_username(session);
 
1006
  if (user == NULL) {
 
1007
    SAFE_FREE(pubkey_64);
 
1008
    return SSH_ERROR;
 
1009
  }
 
1010
 
 
1011
  rc = gethostname(host, sizeof(host));
 
1012
  if (rc < 0) {
 
1013
    SAFE_FREE(user);
 
1014
    SAFE_FREE(pubkey_64);
 
1015
    return SSH_ERROR;
 
1016
  }
 
1017
 
 
1018
  snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n",
 
1019
      ssh_type_to_char(type),
 
1020
      pubkey_64,
 
1021
      user,
 
1022
      host);
 
1023
 
 
1024
  SAFE_FREE(pubkey_64);
 
1025
  SAFE_FREE(user);
 
1026
 
 
1027
  ssh_log(session, SSH_LOG_RARE, "Trying to write public key file: %s", file);
 
1028
  ssh_log(session, SSH_LOG_PACKET, "public key file content: %s", buffer);
 
1029
 
 
1030
  fp = fopen(file, "w+");
 
1031
  if (fp == NULL) {
 
1032
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
1033
        "Error opening %s: %s", file, strerror(errno));
 
1034
    return SSH_ERROR;
 
1035
  }
 
1036
 
 
1037
  len = strlen(buffer);
 
1038
  if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) {
 
1039
    ssh_set_error(session, SSH_REQUEST_DENIED,
 
1040
        "Unable to write to %s", file);
 
1041
    fclose(fp);
 
1042
    unlink(file);
 
1043
    return SSH_ERROR;
 
1044
  }
 
1045
 
 
1046
  fclose(fp);
 
1047
  return SSH_OK;
 
1048
}
 
1049
 
 
1050
/**
 
1051
 * @brief Retrieve a public key from a file.
 
1052
 *
 
1053
 * @param[in]  session  The SSH session to use.
 
1054
 *
 
1055
 * @param[in]  filename The filename of the public key.
 
1056
 *
 
1057
 * @param[out] type     The Pointer to a integer. If it is not NULL, it will
 
1058
 *                      contain the type of the key after execution.
 
1059
 *
 
1060
 * @return              A SSH String containing the public key, or NULL if it
 
1061
 *                      failed.
 
1062
 *
 
1063
 * @see string_free()
 
1064
 * @see publickey_from_privatekey()
 
1065
 */
 
1066
ssh_string publickey_from_file(ssh_session session, const char *filename,
 
1067
    int *type) {
 
1068
  ssh_buffer buffer = NULL;
 
1069
  char buf[4096] = {0};
 
1070
  ssh_string str = NULL;
 
1071
  char *ptr = NULL;
 
1072
  int key_type;
 
1073
  int fd = -1;
 
1074
  int r;
 
1075
 
 
1076
  fd = open(filename, O_RDONLY);
 
1077
  if (fd < 0) {
 
1078
    ssh_set_error(session, SSH_REQUEST_DENIED, "Public key file doesn't exist");
 
1079
    return NULL;
 
1080
  }
 
1081
 
 
1082
  if (read(fd, buf, 8) != 8) {
 
1083
    close(fd);
 
1084
    ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid public key file");
 
1085
    return NULL;
 
1086
  }
 
1087
 
 
1088
  buf[7] = '\0';
 
1089
 
 
1090
  key_type = ssh_type_from_name(buf);
 
1091
  if (key_type == -1) {
 
1092
    close(fd);
 
1093
    ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid public key file");
 
1094
    return NULL;
 
1095
  }
 
1096
 
 
1097
  r = read(fd, buf, sizeof(buf) - 1);
 
1098
  close(fd);
 
1099
  if (r <= 0) {
 
1100
    ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid public key file");
 
1101
    return NULL;
 
1102
  }
 
1103
 
 
1104
  buf[r] = 0;
 
1105
  ptr = strchr(buf, ' ');
 
1106
 
 
1107
  /* eliminate the garbage at end of file */
 
1108
  if (ptr) {
 
1109
    *ptr = '\0';
 
1110
  }
 
1111
 
 
1112
  buffer = base64_to_bin(buf);
 
1113
  if (buffer == NULL) {
 
1114
    ssh_set_error(session, SSH_REQUEST_DENIED, "Invalid public key file");
 
1115
    return NULL;
 
1116
  }
 
1117
 
 
1118
  str = ssh_string_new(buffer_get_rest_len(buffer));
 
1119
  if (str == NULL) {
 
1120
    ssh_set_error(session, SSH_FATAL, "Not enough space");
 
1121
    ssh_buffer_free(buffer);
 
1122
    return NULL;
 
1123
  }
 
1124
 
 
1125
  ssh_string_fill(str, buffer_get_rest(buffer), buffer_get_rest_len(buffer));
 
1126
  ssh_buffer_free(buffer);
 
1127
 
 
1128
  if (type) {
 
1129
    *type = key_type;
 
1130
  }
 
1131
 
 
1132
  return str;
 
1133
}
 
1134
 
 
1135
/**
 
1136
 * @brief Try to read the public key from a given file.
 
1137
 *
 
1138
 * @param[in]  session  The ssh session to use.
 
1139
 *
 
1140
 * @param[in]  keyfile  The name of the private keyfile.
 
1141
 *
 
1142
 * @param[out] publickey A ssh_string to store the public key.
 
1143
 *
 
1144
 * @param[out] type     A pointer to an integer to store the type.
 
1145
 *
 
1146
 * @return              0 on success, -1 on error or the private key doesn't
 
1147
 *                      exist, 1 if the public key doesn't exist.
 
1148
 */
 
1149
int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
 
1150
    ssh_string *publickey, int *type) {
 
1151
  char *pubkey_file;
 
1152
  size_t len;
 
1153
  ssh_string pubkey_string;
 
1154
  int pubkey_type;
 
1155
 
 
1156
  if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
 
1157
    return -1;
 
1158
  }
 
1159
 
 
1160
  if (session->sshdir == NULL) {
 
1161
    if (ssh_options_apply(session) < 0) {
 
1162
      return -1;
 
1163
    }
 
1164
  }
 
1165
 
 
1166
  ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile);
 
1167
  if (!ssh_file_readaccess_ok(keyfile)) {
 
1168
    ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile);
 
1169
    return -1;
 
1170
  }
 
1171
 
 
1172
  len = strlen(keyfile) + 5;
 
1173
  pubkey_file = malloc(len);
 
1174
  if (pubkey_file == NULL) {
 
1175
    return -1;
 
1176
  }
 
1177
  snprintf(pubkey_file, len, "%s.pub", keyfile);
 
1178
 
 
1179
  ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s",
 
1180
                                   pubkey_file);
 
1181
  if (!ssh_file_readaccess_ok(pubkey_file)) {
 
1182
    ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s",
 
1183
                                     pubkey_file);
 
1184
    SAFE_FREE(pubkey_file);
 
1185
    return 1;
 
1186
  }
 
1187
 
 
1188
  ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
 
1189
 
 
1190
  /*
 
1191
   * We are sure both the private and public key file is readable. We return
 
1192
   * the public as a string, and the private filename as an argument
 
1193
   */
 
1194
  pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type);
 
1195
  if (pubkey_string == NULL) {
 
1196
    ssh_log(session, SSH_LOG_PACKET,
 
1197
        "Wasn't able to open public key file %s: %s",
 
1198
        pubkey_file,
 
1199
        ssh_get_error(session));
 
1200
    SAFE_FREE(pubkey_file);
 
1201
    return -1;
 
1202
  }
 
1203
 
 
1204
  SAFE_FREE(pubkey_file);
 
1205
 
 
1206
  *publickey = pubkey_string;
 
1207
  *type = pubkey_type;
 
1208
 
 
1209
  return 0;
 
1210
}
 
1211
 
 
1212
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
 
1213
    char **privkeyfile, int *type) {
 
1214
  const char *priv;
 
1215
  const char *pub;
 
1216
  char *new;
 
1217
  ssh_string pubkey=NULL;
 
1218
 
 
1219
  pub = keytab.publickey;
 
1220
  if (pub == NULL) {
 
1221
    return NULL;
 
1222
  }
 
1223
  priv = keytab.privatekey;
 
1224
  if (priv == NULL) {
 
1225
    return NULL;
 
1226
  }
 
1227
 
 
1228
  if (session->sshdir == NULL) {
 
1229
    if (ssh_options_apply(session) < 0) {
 
1230
      return NULL;
 
1231
    }
 
1232
  }
 
1233
 
 
1234
  ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub);
 
1235
  if (!ssh_file_readaccess_ok(pub)) {
 
1236
    ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub);
 
1237
    goto error;
 
1238
  }
 
1239
 
 
1240
  ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv);
 
1241
  if (!ssh_file_readaccess_ok(priv)) {
 
1242
    ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv);
 
1243
    goto error;
 
1244
  }
 
1245
 
 
1246
  ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
 
1247
 
 
1248
  /*
 
1249
   * We are sure both the private and public key file is readable. We return
 
1250
   * the public as a string, and the private filename as an argument
 
1251
   */
 
1252
  pubkey = publickey_from_file(session, pub, type);
 
1253
  if (pubkey == NULL) {
 
1254
    ssh_log(session, SSH_LOG_PACKET,
 
1255
        "Wasn't able to open public key file %s: %s",
 
1256
        pub,
 
1257
        ssh_get_error(session));
 
1258
    goto error;
 
1259
  }
 
1260
 
 
1261
  new = realloc(*privkeyfile, strlen(priv) + 1);
 
1262
  if (new == NULL) {
 
1263
    ssh_string_free(pubkey);
 
1264
    goto error;
 
1265
  }
 
1266
 
 
1267
  strcpy(new, priv);
 
1268
  *privkeyfile = new;
 
1269
error:
 
1270
  return pubkey;
 
1271
}
 
1272
 
 
1273
/** @} */
 
1274
 
 
1275
/* vim: set ts=4 sw=4 et cindent: */