mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
16 Commits
release-0-
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9f65b5740 | ||
|
|
99a58eb325 | ||
|
|
ed1cba705c | ||
|
|
0b13a6d265 | ||
|
|
74c0201219 | ||
|
|
83c51d1c13 | ||
|
|
c712d30311 | ||
|
|
2144049c7d | ||
|
|
9dd86859e8 | ||
|
|
810fbfb620 | ||
|
|
370d072eba | ||
|
|
56dfa69fc9 | ||
|
|
672f8412f0 | ||
|
|
83ff1ffcc3 | ||
|
|
fb35153b49 | ||
|
|
7539200773 |
@@ -6,15 +6,13 @@ cmake_minimum_required(VERSION 2.6.0)
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION "0.4.0")
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "4")
|
||||
set(APPLICATION_VERSION_PATCH "1")
|
||||
set(APPLICATION_VERSION_PATCH "2")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}${APPLICATION_VERSION_MINOR}${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
set(LIBRARY_VERSION "4.0.1")
|
||||
set(LIBRARY_VERSION "4.0.2")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
|
||||
@@ -13,7 +13,7 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "1")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "2")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
|
||||
15
ChangeLog
15
ChangeLog
@@ -1,6 +1,21 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.4.2 (released 2010-03-15)
|
||||
* Added owner and group information in sftp attributes.
|
||||
* Added missing SSH_OPTIONS_FD option.
|
||||
* Added printout of owner and group in the sftp example.
|
||||
* Added a prepend function for ssh_list.
|
||||
* Added send back replies to openssh's keepalives.
|
||||
* Fixed documentation in scp code
|
||||
* Fixed longname parsing, this only workings with readdir.
|
||||
* Fixed and added support for several identity files.
|
||||
* Fixed sftp_parse_longname() on Windows.
|
||||
* Fixed a race condition bug in ssh_scp_close()
|
||||
* Remove config support for SSHv1 Cipher variable.
|
||||
* Rename ssh_list_add to ssh_list_append.
|
||||
* Rename ssh_list_get_head to ssh_list_pop_head
|
||||
|
||||
version 0.4.1 (released 2010-02-13)
|
||||
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
|
||||
* Added an example for exec.
|
||||
|
||||
@@ -152,10 +152,12 @@ static void do_sftp(ssh_session session){
|
||||
}
|
||||
/* reading the whole directory, file by file */
|
||||
while((file=sftp_readdir(sftp,dir))){
|
||||
fprintf(stderr, "%30s(%.8o) : %.5d.%.5d : %.10llu bytes\n",
|
||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
sftp_attributes_free(file);
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 4
|
||||
#define LIBSSH_VERSION_MICRO 1
|
||||
#define LIBSSH_VERSION_MICRO 2
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -252,6 +252,7 @@ enum ssh_options_e {
|
||||
SSH_OPTIONS_USER,
|
||||
SSH_OPTIONS_SSH_DIR,
|
||||
SSH_OPTIONS_IDENTITY,
|
||||
SSH_OPTIONS_ADD_IDENTITY,
|
||||
SSH_OPTIONS_KNOWNHOSTS,
|
||||
SSH_OPTIONS_TIMEOUT,
|
||||
SSH_OPTIONS_TIMEOUT_USEC,
|
||||
@@ -335,10 +336,14 @@ LIBSSH_API void privatekey_free(ssh_private_key prv);
|
||||
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
int type, const char *passphrase);
|
||||
LIBSSH_API void publickey_free(ssh_public_key key);
|
||||
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
|
||||
ssh_string pubkey, int type);
|
||||
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
int *type);
|
||||
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
|
||||
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
|
||||
LIBSSH_API int ssh_auth_list(ssh_session session);
|
||||
LIBSSH_API char *ssh_basename (const char *path);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
/* in misc.c */
|
||||
/* gets the user home dir. */
|
||||
char *ssh_get_user_home_dir(void);
|
||||
char *ssh_get_local_username(ssh_session session);
|
||||
int ssh_file_readaccess_ok(const char *file);
|
||||
|
||||
/* macro for byte ordering */
|
||||
@@ -46,14 +47,11 @@ struct ssh_iterator {
|
||||
struct ssh_list *ssh_list_new(void);
|
||||
void ssh_list_free(struct ssh_list *list);
|
||||
struct ssh_iterator *ssh_list_get_iterator(const struct ssh_list *list);
|
||||
int ssh_list_add(struct ssh_list *list, const void *data);
|
||||
int ssh_list_append(struct ssh_list *list, const void *data);
|
||||
int ssh_list_prepend(struct ssh_list *list, const void *data);
|
||||
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator);
|
||||
|
||||
/** @brief fetch the head element of a list and remove it from list
|
||||
* @param list the ssh_list to use
|
||||
* @return the first element of the list
|
||||
*/
|
||||
const void *_ssh_list_get_head(struct ssh_list *list);
|
||||
const void *_ssh_list_pop_head(struct ssh_list *list);
|
||||
|
||||
#define ssh_iterator_value(type, iterator)\
|
||||
((type)((iterator)->data))
|
||||
@@ -61,9 +59,9 @@ const void *_ssh_list_get_head(struct ssh_list *list);
|
||||
/** @brief fetch the head element of a list and remove it from list
|
||||
* @param type type of the element to return
|
||||
* @param list the ssh_list to use
|
||||
* @return the first element of the list
|
||||
* @return the first element of the list, or NULL if the list is empty
|
||||
*/
|
||||
#define ssh_list_get_head(type, ssh_list)\
|
||||
((type)_ssh_list_get_head(ssh_list))
|
||||
#define ssh_list_pop_head(type, ssh_list)\
|
||||
((type)_ssh_list_pop_head(ssh_list))
|
||||
|
||||
#endif /* MISC_H_ */
|
||||
|
||||
@@ -104,7 +104,7 @@ struct ssh_session_struct {
|
||||
char *host;
|
||||
char *bindaddr; /* TODO: check if needed */
|
||||
char *xbanner; /* TODO: looks like it is not needed */
|
||||
char *identity;
|
||||
struct ssh_list *identity;
|
||||
char *sshdir;
|
||||
char *knownhosts;
|
||||
char *wanted_methods[10];
|
||||
|
||||
@@ -149,17 +149,16 @@ struct sftp_status_message_struct {
|
||||
char *langmsg;
|
||||
};
|
||||
|
||||
/* don't worry much of these aren't really used */
|
||||
struct sftp_attributes_struct {
|
||||
char *name;
|
||||
char *longname; /* some weird stuff */
|
||||
char *longname; /* ls -l output on openssh, not reliable else */
|
||||
uint32_t flags;
|
||||
uint8_t type;
|
||||
uint64_t size;
|
||||
uint32_t uid;
|
||||
uint32_t gid;
|
||||
char *owner;
|
||||
char *group;
|
||||
char *owner; /* set if openssh and version 4 */
|
||||
char *group; /* set if openssh and version 4 */
|
||||
uint32_t permissions;
|
||||
uint64_t atime64;
|
||||
uint32_t atime;
|
||||
|
||||
269
libssh/auth.c
269
libssh/auth.c
@@ -35,6 +35,7 @@
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/agent.h"
|
||||
#include "libssh/keyfiles.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/packet.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/keys.h"
|
||||
@@ -756,42 +757,6 @@ error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
static const char privKey_1[] = "SSH_DIR/identity";
|
||||
static const char pubKey_1[] = "SSH_DIR/identity.pub";
|
||||
static const char privKey_2[] = "SSH_DIR/id_dsa";
|
||||
static const char pubKey_2[] = "SSH_DIR/id_dsa.pub";
|
||||
static const char privKey_3[] = "SSH_DIR/id_rsa";
|
||||
static const char pubKey_3[] = "SSH_DIR/id_rsa.pub";
|
||||
/** Used different var to allow const char[] declaration */
|
||||
static struct ssh_keys_struct keytab[] = {
|
||||
{ privKey_1, pubKey_1},
|
||||
{ privKey_2, pubKey_2},
|
||||
{ privKey_3, pubKey_3},
|
||||
{0}
|
||||
};
|
||||
#else
|
||||
/* This requires GCC extensions */
|
||||
static struct ssh_keys_struct keytab[] = {
|
||||
{
|
||||
.privatekey = "SSH_DIR/identity",
|
||||
.publickey = "SSH_DIR/identity.pub"
|
||||
},
|
||||
{
|
||||
.privatekey = "SSH_DIR/id_dsa",
|
||||
.publickey = "SSH_DIR/id_dsa.pub",
|
||||
},
|
||||
{
|
||||
.privatekey = "SSH_DIR/id_rsa",
|
||||
.publickey = "SSH_DIR/id_rsa.pub",
|
||||
},
|
||||
{
|
||||
.privatekey = NULL,
|
||||
.publickey = NULL
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Tries to automaticaly authenticate with public key and "none"
|
||||
*
|
||||
@@ -815,13 +780,10 @@ static struct ssh_keys_struct keytab[] = {
|
||||
* @see ssh_options_set()
|
||||
*/
|
||||
int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
|
||||
struct ssh_public_key_struct *publickey;
|
||||
ssh_string pubkey;
|
||||
struct ssh_iterator *it;
|
||||
ssh_private_key privkey;
|
||||
char *privkeyfile = NULL;
|
||||
char *id = NULL;
|
||||
size_t size;
|
||||
unsigned int i = 0;
|
||||
ssh_public_key pubkey;
|
||||
ssh_string pubkey_string;
|
||||
int type = 0;
|
||||
int rc;
|
||||
|
||||
@@ -837,142 +799,170 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
|
||||
/* Try authentication with ssh-agent first */
|
||||
#ifndef _WIN32
|
||||
if (agent_is_running(session)) {
|
||||
char *privkey_file = NULL;
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Trying to authenticate with SSH agent keys as user: %s",
|
||||
session->username);
|
||||
|
||||
for (publickey = agent_get_first_ident(session, &privkeyfile);
|
||||
publickey != NULL;
|
||||
publickey = agent_get_next_ident(session, &privkeyfile)) {
|
||||
for (pubkey = agent_get_first_ident(session, &privkey_file);
|
||||
pubkey != NULL;
|
||||
pubkey = agent_get_next_ident(session, &privkey_file)) {
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkeyfile);
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file);
|
||||
|
||||
pubkey = publickey_to_string(publickey);
|
||||
if (pubkey) {
|
||||
rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey);
|
||||
string_free(pubkey);
|
||||
pubkey_string = publickey_to_string(pubkey);
|
||||
if (pubkey_string) {
|
||||
rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string);
|
||||
string_free(pubkey_string);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
leave_function();
|
||||
|
||||
return rc;
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
ssh_log(session, SSH_LOG_PACKET, "Public key refused by server\n");
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server");
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
continue;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_RARE, "Public key accepted");
|
||||
/* pubkey accepted by server ! */
|
||||
rc = ssh_userauth_agent_pubkey(session, NULL, publickey);
|
||||
rc = ssh_userauth_agent_pubkey(session, NULL, pubkey);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
leave_function();
|
||||
|
||||
return rc;
|
||||
} else if (rc != SSH_AUTH_SUCCESS) {
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Server accepted public key but refused the signature\n"
|
||||
"It might be a bug of libssh\n");
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
"Server accepted public key but refused the signature ;"
|
||||
" It might be a bug of libssh");
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
continue;
|
||||
}
|
||||
/* auth success */
|
||||
ssh_log(session, SSH_LOG_RARE, "Authentication using %s success\n",
|
||||
privkeyfile);
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success",
|
||||
privkey_file);
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
|
||||
leave_function();
|
||||
|
||||
return SSH_AUTH_SUCCESS;
|
||||
} /* if pubkey */
|
||||
SAFE_FREE(id);
|
||||
SAFE_FREE(privkeyfile);
|
||||
publickey_free(publickey);
|
||||
SAFE_FREE(privkey_file);
|
||||
publickey_free(pubkey);
|
||||
} /* for each privkey */
|
||||
} /* if agent is running */
|
||||
#endif
|
||||
|
||||
size = ARRAY_SIZE(keytab);
|
||||
if (session->identity) {
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Trying identity file %s\n", session->identity);
|
||||
for (it = ssh_list_get_iterator(session->identity);
|
||||
it != NULL;
|
||||
it = it->next) {
|
||||
char *privkey_file = NULL;
|
||||
int privkey_open = 0;
|
||||
|
||||
id = malloc(strlen(session->identity) + 1 + 4);
|
||||
if (id == NULL) {
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
sprintf(id, "%s.pub", session->identity);
|
||||
|
||||
keytab[size - 1].privatekey = session->identity;
|
||||
keytab[size - 1].publickey = id;
|
||||
}
|
||||
|
||||
for (i = 0, pubkey = try_publickey_from_file(session, keytab[i],
|
||||
&privkeyfile, &type);
|
||||
i < size;
|
||||
pubkey = try_publickey_from_file(session, keytab[i++],
|
||||
&privkeyfile, &type)) {
|
||||
if (pubkey == NULL) {
|
||||
privkey_file = dir_expand_dup(session, it->data, 1);
|
||||
if (privkey_file == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey);
|
||||
if (rc == SSH_AUTH_ERROR){
|
||||
if (id != NULL) {
|
||||
keytab[size - 1].privatekey = NULL;
|
||||
keytab[size - 1].publickey = NULL;
|
||||
SAFE_FREE(id);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file);
|
||||
|
||||
rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type);
|
||||
if (rc == 1) {
|
||||
char *publickey_file;
|
||||
size_t len;
|
||||
|
||||
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
|
||||
if (privkey == NULL) {
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Reading private key %s failed (bad passphrase ?)",
|
||||
privkey_file);
|
||||
SAFE_FREE(privkey_file);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
string_free(pubkey);
|
||||
SAFE_FREE(privkeyfile);
|
||||
privkey_open = 1;
|
||||
|
||||
pubkey = publickey_from_privatekey(privkey);
|
||||
if (pubkey == NULL) {
|
||||
SAFE_FREE(privkey_file);
|
||||
privatekey_free(privkey);
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
pubkey_string = publickey_to_string(pubkey);
|
||||
type = pubkey->type;
|
||||
publickey_free(pubkey);
|
||||
if (pubkey_string == NULL) {
|
||||
SAFE_FREE(privkey_file);
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
len = strlen(privkey_file) + 5;
|
||||
publickey_file = malloc(len);
|
||||
if (publickey_file == NULL) {
|
||||
SAFE_FREE(privkey_file);
|
||||
ssh_set_error_oom(session);
|
||||
leave_function();
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
snprintf(publickey_file, len, "%s.pub", privkey_file);
|
||||
rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type);
|
||||
if (rc < 0) {
|
||||
ssh_log(session, SSH_LOG_PACKET,
|
||||
"Could not write public key to file: %s", publickey_file);
|
||||
}
|
||||
SAFE_FREE(publickey_file);
|
||||
} else if (rc < 0) {
|
||||
SAFE_FREE(privkey_file);
|
||||
continue;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string);
|
||||
if (rc == SSH_AUTH_ERROR){
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
ssh_log(session, SSH_LOG_RARE, "Publickey authentication error");
|
||||
leave_function();
|
||||
return rc;
|
||||
} else {
|
||||
if (rc != SSH_AUTH_SUCCESS){
|
||||
ssh_log(session, SSH_LOG_RARE, "Publickey refused by server");
|
||||
string_free(pubkey);
|
||||
pubkey = NULL;
|
||||
SAFE_FREE(privkeyfile);
|
||||
privkeyfile = NULL;
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server");
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Public key accepted by server! */
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying to read privatekey %s", privkeyfile);
|
||||
privkey = privatekey_from_file(session, privkeyfile, type, passphrase);
|
||||
if (privkey == NULL) {
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS,
|
||||
"Reading private key %s failed (bad passphrase ?)",
|
||||
privkeyfile);
|
||||
string_free(pubkey);
|
||||
pubkey = NULL;
|
||||
SAFE_FREE(privkeyfile);
|
||||
privkeyfile = NULL;
|
||||
continue; /* continue the loop with other pubkey */
|
||||
if (!privkey_open) {
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s",
|
||||
privkey_file);
|
||||
privkey = privatekey_from_file(session, privkey_file, type, passphrase);
|
||||
if (privkey == NULL) {
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Reading private key %s failed (bad passphrase ?)",
|
||||
privkey_file);
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
continue; /* continue the loop with other pubkey */
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_userauth_pubkey(session, NULL, pubkey, privkey);
|
||||
rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
if (id != NULL) {
|
||||
keytab[size - 1].privatekey = NULL;
|
||||
keytab[size - 1].publickey = NULL;
|
||||
SAFE_FREE(id);
|
||||
}
|
||||
string_free(pubkey);
|
||||
SAFE_FREE(privkeyfile);
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
privatekey_free(privkey);
|
||||
leave_function();
|
||||
return rc;
|
||||
@@ -980,39 +970,28 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) {
|
||||
if (rc != SSH_AUTH_SUCCESS){
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS,
|
||||
"The server accepted the public key but refused the signature");
|
||||
string_free(pubkey);
|
||||
pubkey = NULL;
|
||||
SAFE_FREE(privkeyfile);
|
||||
privkeyfile = NULL;
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
privatekey_free(privkey);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* auth success */
|
||||
ssh_log(session, SSH_LOG_RARE,
|
||||
"Successfully authenticated using %s", privkeyfile);
|
||||
string_free(pubkey);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,
|
||||
"Successfully authenticated using %s", privkey_file);
|
||||
SAFE_FREE(privkey_file);
|
||||
string_free(pubkey_string);
|
||||
privatekey_free(privkey);
|
||||
SAFE_FREE(privkeyfile);
|
||||
if (id != NULL) {
|
||||
keytab[size - 1].privatekey = NULL;
|
||||
keytab[size - 1].publickey = NULL;
|
||||
SAFE_FREE(id);
|
||||
}
|
||||
|
||||
leave_function();
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
/* at this point, pubkey is NULL and so is privkeyfile */
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS,
|
||||
"Tried every public key, none matched");
|
||||
ssh_set_error(session,SSH_NO_ERROR,"No public key matched");
|
||||
if (id) {
|
||||
keytab[size - 1].privatekey = NULL;
|
||||
keytab[size - 1].publickey = NULL;
|
||||
SAFE_FREE(id);
|
||||
}
|
||||
|
||||
leave_function();
|
||||
return SSH_AUTH_DENIED;
|
||||
|
||||
@@ -552,6 +552,15 @@ static void channel_rcv_request(ssh_session session) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(strcmp(request,"keepalive@openssh.com")==0){
|
||||
SAFE_FREE(request);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL,"Responding to Openssh's keepalive");
|
||||
buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_SUCCESS);
|
||||
buffer_add_u32(session->out_buffer, htonl(channel->remote_channel));
|
||||
packet_send(session);
|
||||
leave_function();
|
||||
return;
|
||||
}
|
||||
/* TODO call message_handle since it handles channel requests as messages */
|
||||
/* *but* reset buffer before !! */
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ enum ssh_config_opcode_e {
|
||||
SOC_PORT,
|
||||
SOC_USERNAME,
|
||||
SOC_IDENTITY,
|
||||
SOC_CIPHER,
|
||||
SOC_CIPHERS,
|
||||
SOC_COMPRESSION,
|
||||
SOC_TIMEOUT,
|
||||
@@ -53,7 +52,6 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ "port", SOC_PORT },
|
||||
{ "user", SOC_USERNAME },
|
||||
{ "identityfile", SOC_IDENTITY },
|
||||
{ "cipher", SOC_CIPHER },
|
||||
{ "ciphers", SOC_CIPHERS },
|
||||
{ "compression", SOC_COMPRESSION },
|
||||
{ "connecttimeout", SOC_TIMEOUT },
|
||||
|
||||
@@ -887,6 +887,79 @@ void privatekey_free(ssh_private_key prv) {
|
||||
SAFE_FREE(prv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a public key to a file.
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @param[in] file The filename to write the key into.
|
||||
*
|
||||
* @param[in] pubkey The public key to write.
|
||||
*
|
||||
* @param[in] type The type of the public key.
|
||||
*
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int ssh_publickey_to_file(ssh_session session, const char *file,
|
||||
ssh_string pubkey, int type) {
|
||||
FILE *fp;
|
||||
char *user;
|
||||
char buffer[1024];
|
||||
char host[256];
|
||||
unsigned char *pubkey_64;
|
||||
size_t len;
|
||||
int rc;
|
||||
|
||||
pubkey_64 = bin_to_base64(pubkey->string, string_len(pubkey));
|
||||
if (pubkey_64 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
user = ssh_get_local_username(session);
|
||||
if (user == NULL) {
|
||||
SAFE_FREE(pubkey_64);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = gethostname(host, sizeof(host));
|
||||
if (rc < 0) {
|
||||
SAFE_FREE(user);
|
||||
SAFE_FREE(pubkey_64);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%s %s %s@%s\n",
|
||||
ssh_type_to_char(type),
|
||||
pubkey_64,
|
||||
user,
|
||||
host);
|
||||
|
||||
SAFE_FREE(pubkey_64);
|
||||
SAFE_FREE(user);
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying to write public key file: %s", file);
|
||||
ssh_log(session, SSH_LOG_PACKET, "public key file content: %s", buffer);
|
||||
|
||||
fp = fopen(file, "w+");
|
||||
if (fp == NULL) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Error opening %s: %s", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(buffer);
|
||||
if (fwrite(buffer, len, 1, fp) != 1 || ferror(fp)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Unable to write to %s", file);
|
||||
fclose(fp);
|
||||
unlink(file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Retrieve a public key from a file
|
||||
* \param session the SSH session
|
||||
* \param filename Filename of the key
|
||||
@@ -964,6 +1037,83 @@ ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to read the public key from a given file.
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @param[in] keyfile The name of the private keyfile.
|
||||
*
|
||||
* @param[out] publickey A ssh_string to store the public key.
|
||||
*
|
||||
* @param[out] type A pointer to an integer to store the type.
|
||||
*
|
||||
* @return 0 on success, -1 on error or the private key doesn't
|
||||
* exist, 1 if the public key doesn't exist.
|
||||
*/
|
||||
int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type) {
|
||||
char *pubkey_file;
|
||||
size_t len;
|
||||
ssh_string pubkey_string;
|
||||
int pubkey_type;
|
||||
|
||||
if (session == NULL || keyfile == NULL || publickey == NULL || type == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->sshdir == NULL) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", keyfile);
|
||||
if (!ssh_file_readaccess_ok(keyfile)) {
|
||||
ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", keyfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(keyfile) + 5;
|
||||
pubkey_file = malloc(len);
|
||||
if (pubkey_file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
snprintf(pubkey_file, len, "%s.pub", keyfile);
|
||||
|
||||
ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s",
|
||||
pubkey_file);
|
||||
if (!ssh_file_readaccess_ok(pubkey_file)) {
|
||||
ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s",
|
||||
pubkey_file);
|
||||
SAFE_FREE(pubkey_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_PACKET, "Success opening public and private key");
|
||||
|
||||
/*
|
||||
* We are sure both the private and public key file is readable. We return
|
||||
* the public as a string, and the private filename as an argument
|
||||
*/
|
||||
pubkey_string = publickey_from_file(session, pubkey_file, &pubkey_type);
|
||||
if (pubkey_string == NULL) {
|
||||
ssh_log(session, SSH_LOG_PACKET,
|
||||
"Wasn't able to open public key file %s: %s",
|
||||
pubkey_file,
|
||||
ssh_get_error(session));
|
||||
SAFE_FREE(pubkey_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(pubkey_file);
|
||||
|
||||
*publickey = pubkey_string;
|
||||
*type = pubkey_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab,
|
||||
char **privkeyfile, int *type) {
|
||||
char *public;
|
||||
|
||||
@@ -867,7 +867,7 @@ void message_handle(ssh_session session, uint32_t type){
|
||||
if(!session->ssh_message_list){
|
||||
session->ssh_message_list=ssh_list_new();
|
||||
}
|
||||
ssh_list_add(session->ssh_message_list,msg);
|
||||
ssh_list_append(session->ssh_message_list,msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +158,52 @@ uint64_t ntohll(uint64_t a) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
char *ssh_get_local_username(ssh_session session) {
|
||||
DWORD size = 0;
|
||||
char *user;
|
||||
|
||||
/* get the size */
|
||||
GetUserName(NULL, &size);
|
||||
|
||||
user = malloc(size);
|
||||
if (user == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GetUserName(user, &size)) {
|
||||
return user;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
char *ssh_get_local_username(ssh_session session) {
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
char *name;
|
||||
int rc;
|
||||
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Couldn't retrieve information for current user!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = strdup(pwd.pw_name);
|
||||
|
||||
if (name == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Check if libssh is the required version or get the version
|
||||
* string.
|
||||
@@ -222,7 +268,7 @@ static struct ssh_iterator *ssh_iterator_new(const void *data){
|
||||
return iterator;
|
||||
}
|
||||
|
||||
int ssh_list_add(struct ssh_list *list,const void *data){
|
||||
int ssh_list_append(struct ssh_list *list,const void *data){
|
||||
struct ssh_iterator *iterator=ssh_iterator_new(data);
|
||||
if(!iterator)
|
||||
return SSH_ERROR;
|
||||
@@ -237,6 +283,25 @@ int ssh_list_add(struct ssh_list *list,const void *data){
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_list_prepend(struct ssh_list *list, const void *data){
|
||||
struct ssh_iterator *it = ssh_iterator_new(data);
|
||||
|
||||
if (it == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (list->end == NULL) {
|
||||
/* list is empty */
|
||||
list->root = list->end = it;
|
||||
} else {
|
||||
/* set as new root */
|
||||
it->next = list->root;
|
||||
list->root = it;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
|
||||
struct ssh_iterator *ptr,*prev;
|
||||
prev=NULL;
|
||||
@@ -261,7 +326,14 @@ void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator){
|
||||
SAFE_FREE(iterator);
|
||||
}
|
||||
|
||||
const void *_ssh_list_get_head(struct ssh_list *list){
|
||||
/** @internal
|
||||
* @brief Removes the top element of the list and returns the data value attached
|
||||
* to it
|
||||
* @param list the ssh_list
|
||||
* @returns pointer to the element being stored in head, or
|
||||
* NULL if the list is empty.
|
||||
*/
|
||||
const void *_ssh_list_pop_head(struct ssh_list *list){
|
||||
struct ssh_iterator *iterator=list->root;
|
||||
const void *data;
|
||||
if(!list->root)
|
||||
|
||||
@@ -83,10 +83,29 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
|
||||
}
|
||||
|
||||
if (src->identity) {
|
||||
new->identity = strdup(src->identity);
|
||||
struct ssh_iterator *it;
|
||||
|
||||
new->identity = ssh_list_new();
|
||||
if (new->identity == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
it = ssh_list_get_iterator(src->identity);
|
||||
while (it) {
|
||||
char *id;
|
||||
int rc;
|
||||
|
||||
id = strdup((char *) it->data);
|
||||
if (id == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_list_append(new->identity, id);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
it = it->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (src->sshdir) {
|
||||
@@ -124,29 +143,6 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static char *get_username_from_uid(ssh_session session, uid_t uid){
|
||||
struct passwd *pwd = NULL;
|
||||
char *name;
|
||||
|
||||
pwd = getpwuid(uid);
|
||||
|
||||
if (pwd == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "uid %d doesn't exist !", uid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = strdup(pwd->pw_name);
|
||||
|
||||
if (name == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ssh_options_set_algo(ssh_session session, int algo,
|
||||
const char *list) {
|
||||
if (!verify_existing_algo(algo, list)) {
|
||||
@@ -376,6 +372,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
const void *value) {
|
||||
char *p, *q;
|
||||
long int i;
|
||||
int rc;
|
||||
|
||||
if (session == NULL) {
|
||||
return -1;
|
||||
@@ -439,30 +436,23 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
session->port = i & 0xffff;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_FD:
|
||||
if (value == NULL) {
|
||||
session->fd = -1;
|
||||
} else {
|
||||
socket_t *x = (socket_t *) value;
|
||||
|
||||
session->fd = *x & 0xffff;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_USER:
|
||||
SAFE_FREE(session->username);
|
||||
if (value == NULL) { /* set default username */
|
||||
#ifdef _WIN32
|
||||
DWORD size = 0;
|
||||
GetUserName(NULL, &size); //Get Size
|
||||
q = malloc(size);
|
||||
if (q == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
if (GetUserName(q, &size)) {
|
||||
session->username = q;
|
||||
} else {
|
||||
SAFE_FREE(q);
|
||||
return -1;
|
||||
}
|
||||
#else /* _WIN32 */
|
||||
q = get_username_from_uid(session, getuid());
|
||||
q = ssh_get_local_username(session);
|
||||
if (q == NULL) {
|
||||
return -1;
|
||||
}
|
||||
session->username = q;
|
||||
#endif /* _WIN32 */
|
||||
} else { /* username provided */
|
||||
session->username = strdup(value);
|
||||
if (session->username == NULL) {
|
||||
@@ -489,14 +479,18 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_IDENTITY:
|
||||
|
||||
case SSH_OPTIONS_ADD_IDENTITY:
|
||||
if (value == NULL) {
|
||||
ssh_set_error_invalid(session, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
SAFE_FREE(session->identity);
|
||||
session->identity = dir_expand_dup(session, value, 1);
|
||||
if (session->identity == NULL) {
|
||||
q = dir_expand_dup(session, value, 1);
|
||||
if (q == NULL) {
|
||||
return -1;
|
||||
}
|
||||
rc = ssh_list_prepend(session->identity, q);
|
||||
if (rc < 0) {
|
||||
SAFE_FREE(q);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
30
libssh/scp.c
30
libssh/scp.c
@@ -26,11 +26,18 @@
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/scp.h"
|
||||
/** @defgroup ssh_scp SSH-scp
|
||||
* @brief SCP protocol over SSH functions
|
||||
* @addtogroup ssh_scp
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Creates a new scp session
|
||||
* @param session the SSH session to use
|
||||
* @param mode one of SSH_SCP_WRITE or SSH_SCP_READ, depending if you need to drop files remotely or read them.
|
||||
* It is not possible to combine read and write.
|
||||
* @param location The directory in which write or read will be done. Any push or pull will be relative
|
||||
* to this place
|
||||
* @returns NULL if the creation was impossible.
|
||||
* @returns a ssh_scp handle if it worked.
|
||||
*/
|
||||
@@ -110,11 +117,22 @@ int ssh_scp_init(ssh_scp scp){
|
||||
}
|
||||
|
||||
int ssh_scp_close(ssh_scp scp){
|
||||
char buffer[128];
|
||||
int err;
|
||||
if(scp->channel != NULL){
|
||||
if(channel_send_eof(scp->channel) == SSH_ERROR){
|
||||
scp->state=SSH_SCP_ERROR;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* avoid situations where data are buffered and
|
||||
* not yet stored on disk. This can happen if the close is sent
|
||||
* before we got the EOF back
|
||||
*/
|
||||
while(!channel_is_eof(scp->channel)){
|
||||
err=channel_read(scp->channel,buffer,sizeof(buffer),0);
|
||||
if(err==SSH_ERROR)
|
||||
break;
|
||||
}
|
||||
if(channel_close(scp->channel) == SSH_ERROR){
|
||||
scp->state=SSH_SCP_ERROR;
|
||||
return SSH_ERROR;
|
||||
@@ -138,6 +156,7 @@ void ssh_scp_free(ssh_scp scp){
|
||||
}
|
||||
|
||||
/** @brief creates a directory in a scp in sink mode
|
||||
* @param scp the scp handle.
|
||||
* @param dirname Name of the directory being created.
|
||||
* @param mode Unix permissions for the new directory, e.g. 0755.
|
||||
* @returns SSH_OK if the directory was created.
|
||||
@@ -203,6 +222,7 @@ int ssh_scp_push_directory(ssh_scp scp, const char *dirname, int mode){
|
||||
|
||||
|
||||
/** @brief initializes the sending of a file to a scp in sink mode
|
||||
* @param scp the scp handle.
|
||||
* @param filename Name of the file being sent. It should not contain any path indicator
|
||||
* @param size Exact size in bytes of the file being sent.
|
||||
* @param mode Unix permissions for the new file, e.g. 0644
|
||||
@@ -285,6 +305,7 @@ int ssh_scp_response(ssh_scp scp, char **response){
|
||||
}
|
||||
|
||||
/** @brief Write into a remote scp file
|
||||
* @param scp the scp handle.
|
||||
* @param buffer the buffer to write
|
||||
* @param len the number of bytes to write
|
||||
* @returns SSH_OK the write was successful
|
||||
@@ -331,6 +352,7 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
|
||||
|
||||
/**
|
||||
* @brief reads a string on a channel, terminated by '\n'
|
||||
* @param scp the scp handle.
|
||||
* @param buffer pointer to a buffer to place the string
|
||||
* @param len size of the buffer in bytes. If the string is bigger
|
||||
* than len-1, only len-1 bytes are read and the string
|
||||
@@ -455,6 +477,7 @@ int ssh_scp_pull_request(ssh_scp scp){
|
||||
/**
|
||||
* @brief denies the transfer of a file or creation of a directory
|
||||
* coming from the remote party
|
||||
* @param scp the scp handle.
|
||||
* @param reason nul-terminated string with a human-readable explanation
|
||||
* of the deny
|
||||
* @returns SSH_OK the message was sent
|
||||
@@ -481,6 +504,7 @@ int ssh_scp_deny_request(ssh_scp scp, const char *reason){
|
||||
/**
|
||||
* @brief accepts transfer of a file or creation of a directory
|
||||
* coming from the remote party
|
||||
* @param scp the scp handle.
|
||||
* @returns SSH_OK the message was sent
|
||||
* @returns SSH_ERROR Error sending the message, or sending it in a bad state
|
||||
*/
|
||||
@@ -503,6 +527,7 @@ int ssh_scp_accept_request(ssh_scp scp){
|
||||
}
|
||||
|
||||
/** @brief Read from a remote scp file
|
||||
* @param scp the scp handle.
|
||||
* @param buffer Destination buffer
|
||||
* @param size Size of the buffer
|
||||
* @returns Number of bytes read
|
||||
@@ -585,7 +610,7 @@ int ssh_scp_integer_mode(const char *mode){
|
||||
|
||||
/** @brief Converts a unix mode into a scp string one.
|
||||
* @param mode mode to convert, e.g. 420 or 0644
|
||||
* @retuns pointer to a malloc'ed string containing the scp mode,
|
||||
* @returns pointer to a malloc'ed string containing the scp mode,
|
||||
* e.g. "0644".
|
||||
*/
|
||||
char *ssh_scp_string_mode(int mode){
|
||||
@@ -601,3 +626,6 @@ char *ssh_scp_string_mode(int mode){
|
||||
const char *ssh_scp_request_get_warning(ssh_scp scp){
|
||||
return scp->warning;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -871,7 +871,7 @@ int ssh_execute_message_callbacks(ssh_session session){
|
||||
if(!session->ssh_message_list)
|
||||
return SSH_OK;
|
||||
if(session->ssh_message_callback){
|
||||
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
|
||||
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
|
||||
ret=session->ssh_message_callback(session,msg);
|
||||
if(ret==1){
|
||||
ret = ssh_message_reply_default(msg);
|
||||
@@ -880,7 +880,7 @@ int ssh_execute_message_callbacks(ssh_session session){
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while((msg=ssh_list_get_head(ssh_message , session->ssh_message_list)) != NULL){
|
||||
while((msg=ssh_list_pop_head(ssh_message , session->ssh_message_list)) != NULL){
|
||||
ret = ssh_message_reply_default(msg);
|
||||
if(ret != SSH_OK)
|
||||
return ret;
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
*/
|
||||
ssh_session ssh_new(void) {
|
||||
ssh_session session;
|
||||
char *id;
|
||||
int rc;
|
||||
|
||||
session = malloc(sizeof (struct ssh_session_struct));
|
||||
if (session == NULL) {
|
||||
@@ -95,6 +97,39 @@ ssh_session ssh_new(void) {
|
||||
goto err;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
session->identity = ssh_list_new();
|
||||
if (session->identity == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
id = strdup("SSH_DIR/id_rsa");
|
||||
if (id == NULL) {
|
||||
goto err;
|
||||
}
|
||||
rc = ssh_list_append(session->identity, id);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
id = strdup("SSH_DIR/id_dsa");
|
||||
if (id == NULL) {
|
||||
goto err;
|
||||
}
|
||||
rc = ssh_list_append(session->identity, id);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
id = strdup("SSH_DIR/identity");
|
||||
if (id == NULL) {
|
||||
goto err;
|
||||
}
|
||||
rc = ssh_list_append(session->identity, id);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
return session;
|
||||
|
||||
err:
|
||||
@@ -155,17 +190,27 @@ void ssh_free(ssh_session session) {
|
||||
privatekey_free(session->rsa_key);
|
||||
if(session->ssh_message_list){
|
||||
ssh_message msg;
|
||||
while((msg=ssh_list_get_head(ssh_message ,session->ssh_message_list))
|
||||
while((msg=ssh_list_pop_head(ssh_message ,session->ssh_message_list))
|
||||
!= NULL){
|
||||
ssh_message_free(msg);
|
||||
}
|
||||
ssh_list_free(session->ssh_message_list);
|
||||
}
|
||||
|
||||
if (session->identity) {
|
||||
char *id;
|
||||
|
||||
for (id = ssh_list_pop_head(char *, session->identity);
|
||||
id != NULL;
|
||||
id = ssh_list_pop_head(char *, session->identity)) {
|
||||
SAFE_FREE(id);
|
||||
}
|
||||
ssh_list_free(session->identity);
|
||||
}
|
||||
|
||||
/* options */
|
||||
SAFE_FREE(session->username);
|
||||
SAFE_FREE(session->host);
|
||||
SAFE_FREE(session->identity);
|
||||
SAFE_FREE(session->sshdir);
|
||||
SAFE_FREE(session->knownhosts);
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
/* This file contains code written by Nick Zitzmann */
|
||||
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -1111,6 +1112,54 @@ static sftp_attributes sftp_parse_attr_4(sftp_session sftp, ssh_buffer buf,
|
||||
return attr;
|
||||
}
|
||||
|
||||
enum sftp_longname_field_e {
|
||||
SFTP_LONGNAME_PERM = 0,
|
||||
SFTP_LONGNAME_FIXME,
|
||||
SFTP_LONGNAME_OWNER,
|
||||
SFTP_LONGNAME_GROUP,
|
||||
SFTP_LONGNAME_SIZE,
|
||||
SFTP_LONGNAME_DATE,
|
||||
SFTP_LONGNAME_TIME,
|
||||
SFTP_LONGNAME_NAME,
|
||||
};
|
||||
|
||||
static char *sftp_parse_longname(const char *longname,
|
||||
enum sftp_longname_field_e longname_field) {
|
||||
const char *p, *q;
|
||||
size_t len, field = 0;
|
||||
char *x;
|
||||
|
||||
p = longname;
|
||||
/* Find the beginning of the field which is specified by sftp_longanme_field_e. */
|
||||
while(field != longname_field) {
|
||||
if(isspace(*p)) {
|
||||
field++;
|
||||
p++;
|
||||
while(*p && isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
q = p;
|
||||
while (! isspace(*q)) {
|
||||
q++;
|
||||
}
|
||||
|
||||
/* There is no strndup on windows */
|
||||
len = q - p + 1;
|
||||
x = malloc(len);
|
||||
if (x == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(x, len, "%s", p);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* sftp version 0-3 code. It is different from the v4 */
|
||||
/* maybe a paste of the draft is better than the code */
|
||||
/*
|
||||
@@ -1157,6 +1206,19 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
||||
break;
|
||||
}
|
||||
string_free(longname);
|
||||
|
||||
/* Set owner and group if we talk to openssh and have the longname */
|
||||
if (ssh_get_openssh_version(sftp->session)) {
|
||||
attr->owner = sftp_parse_longname(attr->longname, SFTP_LONGNAME_OWNER);
|
||||
if (attr->owner == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
attr->group = sftp_parse_longname(attr->longname, SFTP_LONGNAME_GROUP);
|
||||
if (attr->group == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer_get_u32(buf, &flags) != sizeof(uint32_t)) {
|
||||
@@ -1254,6 +1316,8 @@ static sftp_attributes sftp_parse_attr_3(sftp_session sftp, ssh_buffer buf,
|
||||
string_free(attr->extended_data);
|
||||
SAFE_FREE(attr->name);
|
||||
SAFE_FREE(attr->longname);
|
||||
SAFE_FREE(attr->owner);
|
||||
SAFE_FREE(attr->group);
|
||||
SAFE_FREE(attr);
|
||||
|
||||
ssh_set_error(sftp->session, SSH_FATAL, "Invalid ATTR structure");
|
||||
|
||||
Reference in New Issue
Block a user