39
40
#include "libssh/priv.h"
41
#include "libssh/buffer.h"
42
#include "libssh/keyfiles.h"
43
#include "libssh/session.h"
44
#include "libssh/wrapper.h"
45
#include "libssh/misc.h"
46
#include "libssh/keys.h"
48
/*todo: remove this include */
49
#include "libssh/string.h"
41
52
#ifdef HAVE_LIBGCRYPT
42
53
#include <gcrypt.h>
92
static u32 char_to_u32(unsigned char *data, u32 size) {
103
static uint32_t char_to_u32(unsigned char *data, uint32_t size) {
96
107
for (i = 0, ret = 0; i < size; ret = ret << 8, ret += data[i++])
101
static u32 asn1_get_len(BUFFER *buffer) {
112
static uint32_t asn1_get_len(ssh_buffer buffer) {
103
114
unsigned char tmp[4];
105
116
if (buffer_get_data(buffer,tmp,1) == 0) {
162
173
size = asn1_get_len(buffer);
163
174
if ((padding = buffer_get_len(buffer) - buffer->pos - size) > 0) {
164
175
for (i = buffer_get_len(buffer) - buffer->pos - size,
165
j = buffer_get(buffer) + size + buffer->pos;
176
j = (unsigned char*)buffer_get(buffer) + size + buffer->pos;
231
242
static int privatekey_decrypt(int algo, int mode, unsigned int key_len,
232
243
unsigned char *iv, unsigned int iv_len,
233
BUFFER *data, ssh_auth_callback cb,
244
ssh_buffer data, ssh_auth_callback cb,
235
246
const char *desc)
331
342
return load_iv(header + iv_pos, *iv, *iv_len);
334
static BUFFER *privatekey_file_to_buffer(FILE *fp, int type,
345
static ssh_buffer privatekey_file_to_buffer(FILE *fp, int type,
335
346
ssh_auth_callback cb, void *userdata, const char *desc) {
336
BUFFER *buffer = NULL;
347
ssh_buffer buffer = NULL;
348
ssh_buffer out = NULL;
338
349
char buf[MAXLINESIZE] = {0};
339
350
unsigned char *iv = NULL;
340
351
const char *header_begin;
446
457
static int read_rsa_privatekey(FILE *fp, gcry_sexp_t *r,
447
458
ssh_auth_callback cb, void *userdata, const char *desc) {
453
STRING *unused1 = NULL;
454
STRING *unused2 = NULL;
457
BUFFER *buffer = NULL;
464
ssh_string unused1 = NULL;
465
ssh_string unused2 = NULL;
468
ssh_buffer buffer = NULL;
460
471
buffer = privatekey_file_to_buffer(fp, TYPE_RSA, cb, userdata, desc);
518
529
static int read_dsa_privatekey(FILE *fp, gcry_sexp_t *r, ssh_auth_callback cb,
519
530
void *userdata, const char *desc) {
520
BUFFER *buffer = NULL;
531
ssh_buffer buffer = NULL;
529
540
buffer = privatekey_file_to_buffer(fp, TYPE_DSS, cb, userdata, desc);
579
590
#ifdef HAVE_LIBCRYPTO
580
591
static int pem_get_password(char *buf, int size, int rwflag, void *userdata) {
581
SSH_SESSION *session = userdata;
592
ssh_session session = userdata;
583
594
/* unused flag */
586
597
ZERO_STRUCTP(buf);
598
ssh_log(session, SSH_LOG_RARE,
599
"Trying to call external authentication function");
588
if (session && session->options->auth_function) {
589
if ((*session->options->auth_function)("Passphrase for private key:", buf, size, 0, 0,
590
session->options->auth_userdata ? session->options->auth_userdata : NULL) < 0) {
601
if (session && session->callbacks->auth_function) {
602
if (session->callbacks->auth_function("Passphrase for private key:", buf, size, 0, 0,
603
session->callbacks->userdata) < 0) {
611
624
* \see privatekey_free()
612
625
* \see publickey_from_privatekey()
614
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session, const char *filename,
627
ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
615
628
int type, const char *passphrase) {
616
629
ssh_auth_callback auth_cb = NULL;
617
PRIVATE_KEY *privkey = NULL;
630
ssh_private_key privkey = NULL;
618
631
void *auth_ud = NULL;
619
632
FILE *file = NULL;
620
633
#ifdef HAVE_LIBGCRYPT
641
ssh_log(session, SSH_LOG_RARE, "Trying to open %s", filename);
628
642
file = fopen(filename,"r");
629
643
if (file == NULL) {
630
644
ssh_set_error(session, SSH_REQUEST_DENIED,
649
ssh_log(session, SSH_LOG_RARE, "Trying to read %s, passphase=%s, authcb=%s",
650
filename, passphrase ? "true" : "false",
651
session->callbacks && session->callbacks->auth_function ? "true" : "false");
637
654
if (passphrase == NULL) {
638
if (session->options->auth_function) {
639
auth_cb = session->options->auth_function;
640
if (session->options->auth_userdata) {
641
auth_ud = session->options->auth_userdata;
655
if (session->callbacks->auth_function) {
656
auth_cb = session->callbacks->auth_function;
657
auth_ud = session->callbacks->userdata;
643
659
#ifdef HAVE_LIBGCRYPT
644
660
valid = read_dsa_privatekey(file, &dsa, auth_cb, auth_ud,
645
661
"Passphrase for private key:");
678
694
if (passphrase == NULL) {
679
if (session->options->auth_function) {
680
auth_cb = session->options->auth_function;
681
if (session->options->auth_userdata) {
682
auth_ud = session->options->auth_userdata;
695
if (session->callbacks && session->callbacks->auth_function) {
696
auth_cb = session->callbacks->auth_function;
697
auth_ud = session->callbacks->userdata;
684
698
#ifdef HAVE_LIBGCRYPT
685
699
valid = read_rsa_privatekey(file, &rsa, auth_cb, auth_ud,
686
700
"Passphrase for private key:");
743
757
/* same that privatekey_from_file() but without any passphrase things. */
744
PRIVATE_KEY *_privatekey_from_file(void *session, const char *filename,
758
ssh_private_key _privatekey_from_file(void *session, const char *filename,
746
PRIVATE_KEY *privkey = NULL;
760
ssh_private_key privkey = NULL;
747
761
FILE *file = NULL;
748
762
#ifdef HAVE_LIBGCRYPT
749
763
gcry_sexp_t dsa = NULL;
843
857
DSA_free(prv->dsa_priv);
844
858
RSA_free(prv->rsa_priv);
846
memset(prv, 0, sizeof(PRIVATE_KEY));
860
memset(prv, 0, sizeof(struct ssh_private_key_struct));
850
864
/** \brief Retrieve a public key from a file
851
865
* \param session the SSH session
852
866
* \param filename Filename of the key
853
* \param _type Pointer to a integer. If it is not null, it contains the type of the key after execution.
867
* \param type Pointer to a integer. If it is not null, it contains the type of the key after execution.
854
868
* \return a SSH String containing the public key, or NULL if it failed.
855
869
* \see string_free()
856
870
* \see publickey_from_privatekey()
858
STRING *publickey_from_file(SSH_SESSION *session, const char *filename,
872
ssh_string publickey_from_file(ssh_session session, const char *filename,
860
BUFFER *buffer = NULL;
874
ssh_buffer buffer = NULL;
861
875
char buf[4096] = {0};
876
ssh_string str = NULL;
863
877
char *ptr = NULL;
927
STRING *try_publickey_from_file(SSH_SESSION *session, struct keys_struct keytab,
941
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
928
942
char **privkeyfile, int *type) {
929
static char *home = NULL;
931
char public[256] = {0};
932
char private[256] = {0};
933
945
const char *priv;
939
home = ssh_get_user_home_dir();
941
ssh_set_error(session,SSH_FATAL,"User home dir impossible to guess");
948
ssh_string pubkey=NULL;
946
950
pub = keytab.publickey;
947
951
if (pub == NULL) {
959
if (session->sshdir == NULL) {
960
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) {
955
965
/* are them readable ? */
956
snprintf(public, sizeof(public), pub, home);
957
ssh_log(session, SSH_LOG_PACKET, "Trying to open public key %s", public);
966
public=dir_expand_dup(session,pub,1);
967
private=dir_expand_dup(session,priv,1);
968
//snprintf(public, sizeof(public), "%s/%s", session->sshdir, pub);
969
//snprintf(private, sizeof(private), "%s/%s", session->sshdir, priv);
971
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", public);
958
972
if (!ssh_file_readaccess_ok(public)) {
959
ssh_log(session, SSH_LOG_PACKET, "Failed");
973
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", public);
963
snprintf(private, sizeof(private), priv, home);
964
ssh_log(session, SSH_LOG_PACKET, "Trying to open private key %s", private);
977
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", private);
965
978
if (!ssh_file_readaccess_ok(private)) {
966
ssh_log(session, SSH_LOG_PACKET, "Failed");
979
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", private);
970
ssh_log(session, SSH_LOG_PACKET, "Success reading public and private key");
983
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
973
986
* We are sure both the private and public key file is readable. We return
1057
1076
* \returns NULL if no match was found or the file was not found
1058
1077
* \returns found_type type of key (ie "dsa","ssh-rsa1"). Don't free that value.
1060
static char **ssh_get_knownhost_line(SSH_SESSION *session, FILE **file,
1079
static char **ssh_get_knownhost_line(ssh_session session, FILE **file,
1061
1080
const char *filename, const char **found_type) {
1062
1081
char buffer[4096] = {0};
1139
1158
* \return 0 if the key doesn't match
1140
1159
* \return -1 on error
1142
static int check_public_key(SSH_SESSION *session, char **tokens) {
1143
STRING *pubkey = session->current_crypto->server_pubkey;
1144
BUFFER *pubkey_buffer;
1161
static int check_public_key(ssh_session session, char **tokens) {
1162
ssh_string pubkey = session->current_crypto->server_pubkey;
1163
ssh_buffer pubkey_buffer;
1145
1164
char *pubkey_64;
1147
1166
/* ok we found some public key in known hosts file. now un-base64it */
1148
1167
if (alldigits(tokens[1])) {
1149
1168
/* openssh rsa1 format */
1170
ssh_string tmpstring;
1152
1171
unsigned int len;
1238
1258
* \returns 1 if it matches
1239
1259
* \returns 0 otherwise
1241
static int match_hashed_host(SSH_SESSION *session, const char *host,
1261
static int match_hashed_host(ssh_session session, const char *host,
1242
1262
const char *sourcehash) {
1243
1263
/* Openssh hash structure :
1244
1264
* |1|base64 encoded salt|base64 encoded hash
1350
1370
* if host key is accepted\n
1351
1371
* SSH_SERVER_ERROR: Some error happened
1353
* \see ssh_options_set_wanted_algo()
1373
* \see ssh_options_set()
1354
1374
* \see ssh_get_pubkey_hash()
1356
1376
* \bug There is no current way to remove or modify an entry into the known
1359
int ssh_is_server_known(SSH_SESSION *session) {
1379
int ssh_is_server_known(ssh_session session) {
1360
1380
FILE *file = NULL;
1367
1387
enter_function();
1369
if (ssh_options_default_known_hosts_file(session->options) < 0) {
1370
ssh_set_error(session, SSH_REQUEST_DENIED,
1371
"Can't find a known_hosts file");
1373
return SSH_SERVER_FILE_NOT_FOUND;
1389
if (session->knownhosts == NULL) {
1390
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
1391
ssh_set_error(session, SSH_REQUEST_DENIED,
1392
"Can't find a known_hosts file");
1394
return SSH_SERVER_FILE_NOT_FOUND;
1376
if (session->options->host == NULL) {
1398
if (session->host == NULL) {
1377
1399
ssh_set_error(session, SSH_FATAL,
1378
1400
"Can't verify host in known hosts if the hostname isn't known");
1379
1401
leave_function();
1380
1402
return SSH_SERVER_ERROR;
1383
host = lowercase(session->options->host);
1405
host = lowercase(session->host);
1384
1406
if (host == NULL) {
1385
1407
ssh_set_error(session, SSH_FATAL, "Not enough space!");
1386
1408
leave_function();
1391
1413
tokens = ssh_get_knownhost_line(session, &file,
1392
session->options->known_hosts_file, &type);
1414
session->knownhosts, &type);
1394
1416
/* End of file, return the current state */
1395
1417
if (tokens == NULL) {
1444
1466
* \param session ssh session
1445
1467
* \return 0 on success, -1 on error
1447
int ssh_write_knownhost(SSH_SESSION *session) {
1448
STRING *pubkey = session->current_crypto->server_pubkey;
1469
int ssh_write_knownhost(ssh_session session) {
1470
ssh_string pubkey = session->current_crypto->server_pubkey;
1449
1471
unsigned char *pubkey_64;
1450
1472
char buffer[4096] = {0};
1453
1475
size_t len = 0;
1455
if (ssh_options_default_known_hosts_file(session->options) < 0) {
1477
if (ssh_options_set(session, SSH_OPTIONS_KNOWNHOSTS, NULL) < 0) {
1456
1478
ssh_set_error(session, SSH_FATAL, "Cannot find known_hosts file.");
1460
if (session->options->host == NULL) {
1482
if (session->host == NULL) {
1461
1483
ssh_set_error(session, SSH_FATAL,
1462
1484
"Cannot write host in known hosts if the hostname is unknown");
1466
1488
/* Check if ~/.ssh exists and create it if not */
1467
dir = ssh_dirname(session->options->known_hosts_file);
1489
dir = ssh_dirname(session->knownhosts);
1468
1490
if (dir == NULL) {
1469
1491
ssh_set_error(session, SSH_FATAL, "%s", strerror(errno));
1480
1502
SAFE_FREE(dir);
1482
file = fopen(session->options->known_hosts_file, "a");
1504
file = fopen(session->knownhosts, "a");
1483
1505
if (file == NULL) {
1484
1506
ssh_set_error(session, SSH_FATAL,
1485
1507
"Couldn't open known_hosts file %s for appending: %s",
1486
session->options->known_hosts_file, strerror(errno));
1508
session->knownhosts, strerror(errno));
1490
1512
if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) {
1491
1513
/* openssh uses a different format for ssh-rsa1 keys.
1492
1514
Be compatible --kv */
1494
1516
char *e_string = NULL;
1495
1517
char *n_string = NULL;
1496
1518
bignum e = NULL;