aboutsummaryrefslogtreecommitdiff
path: root/libssh
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2008-11-24 18:05:55 +0000
committerAris Adamantiadis <aris@0xbadc0de.be>2008-11-24 18:05:55 +0000
commitf7700f2bc2f2d5876c91bbbf3eaae233ee1548b1 (patch)
tree5e80eb3b78683d183d47759582f9712e23bf84b6 /libssh
parentf880011d727e598561fe64a805a2fb22a39ffcee (diff)
downloadlibssh-f7700f2bc2f2d5876c91bbbf3eaae233ee1548b1.tar.gz
libssh-f7700f2bc2f2d5876c91bbbf3eaae233ee1548b1.tar.xz
libssh-f7700f2bc2f2d5876c91bbbf3eaae233ee1548b1.zip
patches 0001-Save-the-last-error-and-provide-a-function-to-get-it.patch,
0002-Use-const-whereever-it-makes-sense.patch, 0003-Implement-function-to-retrieve-userauth-possabilitie.patch from Andreas Schneider git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@191 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh')
-rw-r--r--libssh/auth.c63
-rw-r--r--libssh/dh.c2
-rw-r--r--libssh/error.c2
-rw-r--r--libssh/kex.c18
-rw-r--r--libssh/options.c18
-rw-r--r--libssh/session.c1
-rw-r--r--libssh/sftp.c189
-rw-r--r--libssh/string.c4
8 files changed, 198 insertions, 99 deletions
diff --git a/libssh/auth.c b/libssh/auth.c
index 24d3cd72..29054884 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -52,9 +52,10 @@ static void burn(char *ptr){
static int wait_auth_status(SSH_SESSION *session,int kbdint){
int err=SSH_AUTH_ERROR;
int cont=1;
- STRING *can_continue;
+ STRING *auth;
u8 partial=0;
- char *c_cont;
+ int todo = 0;
+ char *auth_methods = NULL;
enter_function();
while(cont){
if(packet_read(session))
@@ -63,24 +64,39 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
break;
switch(session->in_packet.type){
case SSH2_MSG_USERAUTH_FAILURE:
- can_continue=buffer_get_ssh_string(session->in_buffer);
- if(!can_continue || buffer_get_u8(session->in_buffer,&partial)!=1 ){
+ auth = buffer_get_ssh_string(session->in_buffer);
+ if(!auth || buffer_get_u8(session->in_buffer,&partial)!=1 ){
ssh_set_error(session,SSH_FATAL,
"invalid SSH_MSG_USERAUTH_FAILURE message");
leave_function();
return SSH_AUTH_ERROR;
}
- c_cont=string_to_char(can_continue);
- if(partial){
+ auth_methods = string_to_char(auth);
+ if(partial) {
err=SSH_AUTH_PARTIAL;
- ssh_set_error(session,SSH_NO_ERROR,"partial success, authentications that can continue : %s",c_cont);
- }
- else {
+ ssh_set_error(session,SSH_NO_ERROR,"partial success, authentications that can continue : %s", auth_methods);
+ } else {
err=SSH_AUTH_DENIED;
- ssh_set_error(session,SSH_REQUEST_DENIED,"Access denied. authentications that can continue : %s",c_cont);
+ ssh_set_error(session,SSH_REQUEST_DENIED,"Access denied. authentications that can continue : %s", auth_methods);
+
+ session->auth_methods = 0;
+ if (strstr(auth_methods, "password") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
+ }
+ if (strstr(auth_methods, "keyboard-interactive") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
+ }
+ if (strstr(auth_methods, "publickey") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
+ }
+ if (strstr(auth_methods, "hostbased") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED;
+ }
}
- free(can_continue);
- free(c_cont);
+
+
+ free(auth);
+ free(auth_methods);
cont=0;
break;
case SSH2_MSG_USERAUTH_PK_OK:
@@ -120,6 +136,13 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
return err;
}
+int ssh_auth_list(SSH_SESSION *session) {
+ if (session == NULL) {
+ return -1;
+ }
+ return session->auth_methods;
+}
+
/* use the "none" authentication question */
/** \brief Try to authenticate through the "none" method
@@ -132,7 +155,7 @@ static int wait_auth_status(SSH_SESSION *session,int kbdint){
* SSH_AUTH_SUCCESS : Authentication success
*/
-int ssh_userauth_none(SSH_SESSION *session,char *username){
+int ssh_userauth_none(SSH_SESSION *session, const char *username){
STRING *user;
STRING *service;
STRING *method;
@@ -188,7 +211,7 @@ int ssh_userauth_none(SSH_SESSION *session,char *username){
* \see ssh_userauth_pubkey()
*/
-int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STRING *publickey){
+int ssh_userauth_offer_pubkey(SSH_SESSION *session, const char *username,int type, STRING *publickey){
STRING *user;
STRING *service;
STRING *method;
@@ -253,7 +276,7 @@ int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,int type, STR
* \see ssh_userauth_offer_pubkey()
*/
-int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey, PRIVATE_KEY *privatekey){
+int ssh_userauth_pubkey(SSH_SESSION *session, const char *username, STRING *publickey, PRIVATE_KEY *privatekey){
STRING *user;
STRING *service;
STRING *method;
@@ -317,7 +340,7 @@ int ssh_userauth_pubkey(SSH_SESSION *session, char *username, STRING *publickey,
*/
-int ssh_userauth_password(SSH_SESSION *session,char *username,char *password){
+int ssh_userauth_password(SSH_SESSION *session, const char *username, const char *password){
STRING *user;
STRING *service;
STRING *method;
@@ -556,7 +579,7 @@ static void kbdint_clean(struct ssh_kbdint *kbd){
/* this function sends the first packet as explained in section 3.1
* of the draft */
static int kbdauth_init(SSH_SESSION *session,
- char *user, char *submethods){
+ const char *user, const char *submethods){
STRING *user_s=string_from_char(user);
STRING *submethods_s=(submethods ? string_from_char(submethods): string_from_char(""));
STRING *service=string_from_char("ssh-connection");
@@ -684,7 +707,7 @@ static int kbdauth_send(SSH_SESSION *session) {
/* the heart of the whole keyboard interactive login */
-int ssh_userauth_kbdint(SSH_SESSION *session,char *user,char *submethods){
+int ssh_userauth_kbdint(SSH_SESSION *session, const char *user, const char *submethods){
int err;
if(session->version==1)
return SSH_AUTH_DENIED; // no keyb-interactive for ssh1
@@ -779,7 +802,7 @@ char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session){
* \returns pointer to the prompt. Do not free it
*/
-char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, int i,
+char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, int i,
char *echo){
if(i > session->kbdint->nprompts || i<0)
return NULL;
@@ -796,7 +819,7 @@ char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session, int i,
* \param answer answer to give to server
*/
-void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *answer){
+void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, const char *answer){
if (i>session->kbdint->nprompts)
return;
if(!session->kbdint->answers){
diff --git a/libssh/dh.c b/libssh/dh.c
index 35d130c2..e248433d 100644
--- a/libssh/dh.c
+++ b/libssh/dh.c
@@ -129,7 +129,7 @@ void ssh_print_bignum(char *which,bignum num){
free(hex);
}
-void ssh_print_hexa(char *descr,unsigned char *what, int len){
+void ssh_print_hexa(char *descr, const unsigned char *what, int len){
int i;
printf("%s : ",descr);
if(len>16)
diff --git a/libssh/error.c b/libssh/error.c
index 828a67ca..2ad6777d 100644
--- a/libssh/error.c
+++ b/libssh/error.c
@@ -64,7 +64,7 @@ int ssh_get_error_code(void *error){
return err->error_code;
}
-void ssh_say(int priority, char *format,...){
+void ssh_say(int priority, const char *format, ...){
va_list va;
va_start(va,format);
if(priority <= verbosity)
diff --git a/libssh/kex.c b/libssh/kex.c
index 9838a7c5..b5a2f633 100644
--- a/libssh/kex.c
+++ b/libssh/kex.c
@@ -63,11 +63,12 @@ char *ssh_kex_nums[]={
"compression algo server->client","languages client->server","languages server->client",NULL};
/* tokenize will return a token of strings delimited by ",". the first element has to be freed */
-static char **tokenize(char *chain){
+static char **tokenize(const char *chain){
char **tokens;
int n=1;
int i=0;
- char *ptr=chain=strdup(chain);
+ char *tmp = strdup(chain);
+ char *ptr = tmp;
while(*ptr){
if(*ptr==','){
n++;
@@ -77,7 +78,7 @@ static char **tokenize(char *chain){
}
/* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
tokens=malloc(sizeof(char *) * (n+1) ); /* +1 for the null */
- ptr=chain;
+ ptr=tmp;
for(i=0;i<n;i++){
tokens[i]=ptr;
while(*ptr)
@@ -89,11 +90,12 @@ static char **tokenize(char *chain){
}
/* same as tokenize(), but with spaces instead of ',' */
-char **space_tokenize(char *chain){
+char **space_tokenize(const char *chain){
char **tokens;
int n=1;
int i=0;
- char *ptr=chain=strdup(chain);
+ char *tmp = strdup(chain);
+ char *ptr = tmp;
while(*ptr==' ')
++ptr; /* skip initial spaces */
while(*ptr){
@@ -108,7 +110,7 @@ char **space_tokenize(char *chain){
}
/* now n contains the number of tokens, the first possibly empty if the list was empty too e.g. "" */
tokens=malloc(sizeof(char *) * (n+1) ); /* +1 for the null */
- ptr=chain; /* we don't pass the initial spaces because the "chain" pointer is needed by the caller */
+ ptr=tmp; /* we don't pass the initial spaces because the "tmp" pointer is needed by the caller */
/* function to free the tokens. */
for(i=0;i<n;i++){
tokens[i]=ptr;
@@ -128,7 +130,7 @@ char **space_tokenize(char *chain){
/* and a list of prefered objects (what_d) */
/* it will return a strduped pointer on the first prefered object found in the available objects list */
-char *ssh_find_matching(char *in_d, char *what_d){
+char *ssh_find_matching(const char *in_d, const char *what_d){
char ** tok_in, **tok_what;
int i_in, i_what;
char *ret;
@@ -272,7 +274,7 @@ void ssh_send_kex(SSH_SESSION *session, int server_kex){
}
/* returns 1 if at least one of the name algos is in the default algorithms table */
-int verify_existing_algo(int algo, char *name){
+int verify_existing_algo(int algo, const char *name){
char *ptr;
if(algo>9 || algo <0)
return -1;
diff --git a/libssh/options.c b/libssh/options.c
index 570ef412..d95b3292 100644
--- a/libssh/options.c
+++ b/libssh/options.c
@@ -166,7 +166,7 @@ void ssh_options_set_host(SSH_OPTIONS *opt, const char *hostname){
* \param opt options structure
* \param username user name to authenticate
*/
-void ssh_options_set_username(SSH_OPTIONS *opt, char *username){
+void ssh_options_set_username(SSH_OPTIONS *opt, const char *username){
if(opt->username)
free(opt->username);
opt->username=strdup(username);
@@ -193,7 +193,7 @@ void ssh_options_set_fd(SSH_OPTIONS *opt, socket_t fd){
* \param bindaddr bind address in form of hostname or ip address
* \param port port number to bind
*/
-void ssh_options_set_bind(SSH_OPTIONS *opt, char *bindaddr,int port){
+void ssh_options_set_bind(SSH_OPTIONS *opt, const char *bindaddr, int port){
opt->bindaddr=strdup(bindaddr);
opt->bindport=port;
}
@@ -206,7 +206,7 @@ void ssh_options_set_bind(SSH_OPTIONS *opt, char *bindaddr,int port){
* the user home directory
* \see ssh_options_set_user_home_dir()
*/
-void ssh_options_set_ssh_dir(SSH_OPTIONS *opt, char *dir){
+void ssh_options_set_ssh_dir(SSH_OPTIONS *opt, const char *dir){
char buffer[1024];
snprintf(buffer,1024,dir,ssh_get_user_home_dir());
opt->ssh_dir=strdup(buffer);
@@ -219,7 +219,7 @@ void ssh_options_set_ssh_dir(SSH_OPTIONS *opt, char *dir){
* with the user home directory
* \see ssh_options_set_user_home_dir()
*/
-void ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir){
+void ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, const char *dir){
char buffer[1024];
snprintf(buffer,1024,dir,ssh_get_user_home_dir());
opt->known_hosts_file=strdup(buffer);
@@ -232,7 +232,7 @@ void ssh_options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir){
* with the user home directory
* \see ssh_options_set_user_home_dir()
*/
-void ssh_options_set_identity(SSH_OPTIONS *opt, char *identity){
+void ssh_options_set_identity(SSH_OPTIONS *opt, const char *identity){
char buffer[1024];
snprintf(buffer,1024,identity,ssh_get_user_home_dir());
opt->identity=strdup(buffer);
@@ -241,13 +241,13 @@ void ssh_options_set_identity(SSH_OPTIONS *opt, char *identity){
/** \warning I don't remember what these functions are supposed
* to set
*/
-void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, char *dsakey){
+void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, const char *dsakey){
opt->dsakey=strdup(dsakey);
}
/** \warning I don't remember what these functions are supposed
* to set
*/
-void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, char *rsakey){
+void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, const char *rsakey){
opt->rsakey=strdup(rsakey);
}
@@ -255,7 +255,7 @@ void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, char *rsakey){
* \param opt options structure
* \param banner a text banner to be shown
*/
-void ssh_options_set_banner(SSH_OPTIONS *opt, char *banner){
+void ssh_options_set_banner(SSH_OPTIONS *opt, const char *banner){
if(opt->banner)
free(opt->banner);
opt->banner=strdup(banner);
@@ -277,7 +277,7 @@ void ssh_options_set_banner(SSH_OPTIONS *opt, char *banner){
* \param list list of algorithms to be used, in order of preference and separated by commas
* \return 0 on success, -1 on error (most likely an algorithm is not available)
*/
-int ssh_options_set_wanted_algos(SSH_OPTIONS *opt,int algo, char *list){
+int ssh_options_set_wanted_algos(SSH_OPTIONS *opt, int algo, const char *list){
if(algo > SSH_LANG_S_C || algo < 0){
ssh_set_error(opt,SSH_REQUEST_DENIED,"algo %d out of range",algo);
return -1;
diff --git a/libssh/session.c b/libssh/session.c
index dc485ec8..877c44a1 100644
--- a/libssh/session.c
+++ b/libssh/session.c
@@ -43,6 +43,7 @@ SSH_SESSION *ssh_new() {
session->maxchannel=FIRST_CHANNEL;
session->socket=ssh_socket_new(session);
session->alive=0;
+ session->auth_methods=0;
session->blocking=1;
session->log_indent=0;
session->out_buffer=buffer_new();
diff --git a/libssh/sftp.c b/libssh/sftp.c
index d69bb927..14988d34 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -28,6 +28,7 @@ MA 02111-1307, USA. */
/** \addtogroup ssh_sftp
* @{ */
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
@@ -49,6 +50,7 @@ MA 02111-1307, USA. */
/* functions */
void sftp_enqueue(SFTP_SESSION *session, SFTP_MESSAGE *msg);
static void sftp_message_free(SFTP_MESSAGE *msg);
+static void sftp_set_errno(SFTP_SESSION *sftp, int errnum);
/** \brief start a new SFTP session
* \param session the SSH session
@@ -188,6 +190,20 @@ SFTP_PACKET *sftp_packet_read(SFTP_SESSION *sftp){
return packet;
}
+static void sftp_set_errno(SFTP_SESSION *sftp, int errnum) {
+ if (sftp != NULL) {
+ sftp->errnum = errnum;
+ }
+}
+
+int sftp_get_error(SFTP_SESSION *sftp) {
+ if (sftp == NULL) {
+ return -1;
+ }
+
+ return sftp->errnum;
+}
+
static SFTP_MESSAGE *sftp_message_new(SFTP_SESSION *sftp){
sftp_enter_function();
SFTP_MESSAGE *msg=malloc(sizeof(SFTP_MESSAGE));
@@ -419,6 +435,7 @@ SFTP_FILE *parse_handle_msg(SFTP_MESSAGE *msg){
}
return file;
}
+
/** \brief open a directory
* \param sftp SFTP session handle
* \param path path to the directory
@@ -426,7 +443,7 @@ SFTP_FILE *parse_handle_msg(SFTP_MESSAGE *msg){
* \see sftp_readdir()
* \see sftp_dir_close()
*/
-SFTP_DIR *sftp_opendir(SFTP_SESSION *sftp, char *path){
+SFTP_DIR *sftp_opendir(SFTP_SESSION *sftp, const char *path){
SFTP_DIR *dir=NULL;
SFTP_FILE *file;
STATUS_MESSAGE *status;
@@ -452,6 +469,7 @@ SFTP_DIR *sftp_opendir(SFTP_SESSION *sftp, char *path){
sftp_message_free(msg);
if(!status)
return NULL;
+ sftp_set_errno(sftp, status->status);
ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
status_msg_free(status);
return NULL;
@@ -760,10 +778,14 @@ SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *sftp, SFTP_DIR *dir){
sftp_message_free(msg);
if(!status)
return NULL;
- if(status->status==SSH_FX_EOF){
- dir->eof=1;
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_EOF:
+ dir->eof = 1;
status_msg_free(status);
return NULL;
+ default:
+ break;
}
ssh_set_error(sftp->session,SSH_FATAL,"Unknown error status : %d",status->status);
status_msg_free(status);
@@ -849,12 +871,18 @@ static int sftp_handle_close(SFTP_SESSION *sftp, STRING *handle){
sftp_message_free(msg);
if(!status)
return -1;
- if(status->status != SSH_FX_OK){
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
- err=-1;
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
+ status_msg_free(status);
+ return err;
+ break;
+ default:
+ break;
}
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
status_msg_free(status);
- return err;
+ return -1;
default:
ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during sftp_handle_close!",msg->packet_type);
sftp_message_free(msg);
@@ -903,7 +931,7 @@ int sftp_dir_close(SFTP_DIR *dir){
/** \brief Open a remote file
* \todo please complete doc
*/
-SFTP_FILE *sftp_open(SFTP_SESSION *sftp, char *file, int access, SFTP_ATTRIBUTES *attr){
+SFTP_FILE *sftp_open(SFTP_SESSION *sftp, const char *file, int access, SFTP_ATTRIBUTES *attr){
SFTP_FILE *handle;
SFTP_MESSAGE *msg=NULL;
STATUS_MESSAGE *status;
@@ -943,6 +971,7 @@ SFTP_FILE *sftp_open(SFTP_SESSION *sftp, char *file, int access, SFTP_ATTRIBUTES
sftp_message_free(msg);
if(!status)
return NULL;
+ sftp_set_errno(sftp, status->status);
ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
status_msg_free(status);
return NULL;
@@ -1000,14 +1029,18 @@ int sftp_read(SFTP_FILE *handle, void *data, int len){
sftp_message_free(msg);
if(!status)
return -1;
- if(status->status != SSH_FX_EOF){
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
- err=-1;
- }
- else
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_EOF:
handle->eof=1;
+ status_msg_free(status);
+ return err ? err : 0;
+ default:
+ break;
+ }
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
status_msg_free(status);
- return err?err:0;
+ return -1;
case SSH_FXP_DATA:
datastring=buffer_get_ssh_string(msg->payload);
sftp_message_free(msg);
@@ -1120,6 +1153,7 @@ int sftp_async_read(SFTP_FILE *file, void *data, int size, u32 id){
sftp_leave_function();
return -1;
}
+ sftp_set_errno(sftp, status->status);
if(status->status != SSH_FX_EOF){
ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
sftp_leave_function();
@@ -1161,7 +1195,7 @@ int sftp_async_read(SFTP_FILE *file, void *data, int size, u32 id){
sftp_leave_function();
}
-int sftp_write(SFTP_FILE *file, void *data, int len){
+int sftp_write(SFTP_FILE *file, const void *data, int len){
SFTP_MESSAGE *msg=NULL;
STATUS_MESSAGE *status;
STRING *datastring;
@@ -1194,13 +1228,19 @@ int sftp_write(SFTP_FILE *file, void *data, int len){
sftp_message_free(msg);
if(!status)
return -1;
- if(status->status != SSH_FX_OK){
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
- err=-1;
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
+ file->offset+=len;
+ status_msg_free(status);
+ return err ? err : len;
+ default:
+ break;
}
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
file->offset+=len;
status_msg_free(status);
- return (err?err:len);
+ return -1;
default:
ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during write!",msg->packet_type);
sftp_message_free(msg);
@@ -1246,14 +1286,18 @@ int sftp_rm(SFTP_SESSION *sftp, char *file) {
sftp_message_free(msg);
if (!status)
return -1;
- if (status->status != SSH_FX_OK) {
- /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
- status_msg_free(status);
- return -1;
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
+ status_msg_free(status);
+ return 0;
+ default:
+ break;
}
+ /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
status_msg_free(status);
- return 0; /* at this point, everything turned out OK */
+ return -1;
} else {
ssh_set_error(sftp->session,SSH_FATAL, "Received message %d when attempting to remove file", msg->packet_type);
sftp_message_free(msg);
@@ -1262,7 +1306,7 @@ int sftp_rm(SFTP_SESSION *sftp, char *file) {
}
/* code written by Nick */
-int sftp_rmdir(SFTP_SESSION *sftp, char *directory) {
+int sftp_rmdir(SFTP_SESSION *sftp, const char *directory) {
u32 id = sftp_get_new_id(sftp);
BUFFER *buffer = buffer_new();
STRING *filename = string_from_char(directory);
@@ -1285,18 +1329,21 @@ int sftp_rmdir(SFTP_SESSION *sftp, char *directory) {
{
status = parse_status_msg(msg);
sftp_message_free(msg);
- if (!status)
- {
+ if (!status) {
return -1;
}
- else if (status->status != SSH_FX_OK) /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
- {
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
status_msg_free(status);
- return -1;
+ return 0;
+ break;
+ default:
+ break;
}
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
status_msg_free(status);
- return 0; /* at this point, everything turned out OK */
+ return -1;
}
else
{
@@ -1307,12 +1354,13 @@ int sftp_rmdir(SFTP_SESSION *sftp, char *directory) {
}
/* Code written by Nick */
-int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr) {
+int sftp_mkdir(SFTP_SESSION *sftp, const char *directory, SFTP_ATTRIBUTES *attr) {
u32 id = sftp_get_new_id(sftp);
BUFFER *buffer = buffer_new();
STRING *path = string_from_char(directory);
SFTP_MESSAGE *msg = NULL;
STATUS_MESSAGE *status = NULL;
+ SFTP_ATTRIBUTES *errno_attr = NULL;
buffer_add_u32(buffer, id);
buffer_add_ssh_string(buffer, path);
@@ -1329,17 +1377,33 @@ int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr) {
/* by specification, this command's only supposed to return SSH_FXP_STATUS */
status = parse_status_msg(msg);
sftp_message_free(msg);
- if (!status)
- return -1;
- else
- if (status->status != SSH_FX_OK) {
- /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
+ if (status == NULL) {
+ return -1;
+ }
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_FAILURE:
+ /*
+ * mkdir always returns a failure, even if the path already exists.
+ * To be POSIX conform and to be able to map it to EEXIST a stat
+ * call should be issued here
+ */
+ errno_attr = sftp_lstat(sftp, directory);
+ if (errno_attr != NULL) {
+ sftp_set_errno(sftp, SSH_FX_FILE_ALREADY_EXISTS);
+ }
+ break;
+ case SSH_FX_OK:
status_msg_free(status);
- return -1;
+ return 0;
+ break;
+ default:
+ break;
}
+ /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
status_msg_free(status);
- return 0; /* at this point, everything turned out OK */
+ return -1;
} else {
ssh_set_error(sftp->session,SSH_FATAL, "Received message %d when attempting to make directory", msg->packet_type);
sftp_message_free(msg);
@@ -1348,7 +1412,7 @@ int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr) {
}
/* code written by nick */
-int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname) {
+int sftp_rename(SFTP_SESSION *sftp, const char *original, const char *newname) {
u32 id = sftp_get_new_id(sftp);
BUFFER *buffer = buffer_new();
STRING *oldpath = string_from_char(original);
@@ -1374,14 +1438,18 @@ int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname) {
sftp_message_free(msg);
if (!status)
return -1;
- else if (status->status != SSH_FX_OK) {
- /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
status_msg_free(status);
- return -1;
+ return 0;
+ default:
+ break;
}
+ /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
status_msg_free(status);
- return 0; /* at this point, everything turned out OK */
+ return -1;
} else {
ssh_set_error(sftp->session,SSH_FATAL, "Received message %d when attempting to rename", msg->packet_type);
sftp_message_free(msg);
@@ -1390,7 +1458,7 @@ int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname) {
}
/* Code written by Nick */
-int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr) {
+int sftp_setstat(SFTP_SESSION *sftp, const char *file, SFTP_ATTRIBUTES *attr) {
u32 id = sftp_get_new_id(sftp);
BUFFER *buffer = buffer_new();
STRING *path = string_from_char(file);
@@ -1414,14 +1482,18 @@ int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr) {
sftp_message_free(msg);
if (!status)
return -1;
- else if (status->status != SSH_FX_OK) {
- /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
+ sftp_set_errno(sftp, status->status);
+ switch (status->status) {
+ case SSH_FX_OK:
status_msg_free(status);
- return -1;
+ return 0;
+ default:
+ break;
}
+ /* status should be SSH_FX_OK if the command was successful, if it didn't, then there was an error */
+ ssh_set_error(sftp->session,SSH_REQUEST_DENIED, "sftp server: %s", status->errormsg);
status_msg_free(status);
- return 0; /* at this point, everything turned out OK */
+ return -1;
} else {
ssh_set_error(sftp->session,SSH_FATAL, "Received message %d when attempting to set stats", msg->packet_type);
sftp_message_free(msg);
@@ -1430,7 +1502,7 @@ int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr) {
}
/* another code written by Nick */
-char *sftp_canonicalize_path(SFTP_SESSION *sftp, char *path)
+char *sftp_canonicalize_path(SFTP_SESSION *sftp, const char *path)
{
u32 id = sftp_get_new_id(sftp);
BUFFER *buffer = buffer_new();
@@ -1477,7 +1549,7 @@ char *sftp_canonicalize_path(SFTP_SESSION *sftp, char *path)
return NULL;
}
-SFTP_ATTRIBUTES *sftp_xstat(SFTP_SESSION *sftp, char *path,int param){
+SFTP_ATTRIBUTES *sftp_xstat(SFTP_SESSION *sftp, const char *path, int param){
u32 id=sftp_get_new_id(sftp);
BUFFER *buffer=buffer_new();
STRING *pathstr= string_from_char(path);
@@ -1504,6 +1576,7 @@ SFTP_ATTRIBUTES *sftp_xstat(SFTP_SESSION *sftp, char *path,int param){
sftp_message_free(msg);
if(!status)
return NULL;
+ sftp_set_errno(sftp, status->status);
ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server: %s",status->errormsg);
status_msg_free(status);
return NULL;
@@ -1513,10 +1586,10 @@ SFTP_ATTRIBUTES *sftp_xstat(SFTP_SESSION *sftp, char *path,int param){
return NULL;
}
-SFTP_ATTRIBUTES *sftp_stat(SFTP_SESSION *session, char *path){
+SFTP_ATTRIBUTES *sftp_stat(SFTP_SESSION *session, const char *path){
return sftp_xstat(session,path,SSH_FXP_STAT);
}
-SFTP_ATTRIBUTES *sftp_lstat(SFTP_SESSION *session, char *path){
+SFTP_ATTRIBUTES *sftp_lstat(SFTP_SESSION *session, const char *path){
return sftp_xstat(session,path,SSH_FXP_LSTAT);
}
diff --git a/libssh/string.c b/libssh/string.c
index 18ad0dbb..45bd02cf 100644
--- a/libssh/string.c
+++ b/libssh/string.c
@@ -39,7 +39,7 @@ STRING *string_new(unsigned int size){
return str;
}
-void string_fill(STRING *str,void *data,int len){
+void string_fill(STRING *str, const void *data,int len){
memcpy(str->string,data,len);
}
@@ -49,7 +49,7 @@ void string_fill(STRING *str,void *data,int len){
* \return the newly allocated string.
* \warning The nul byte is not copied nor counted in the ouput string.
*/
-STRING *string_from_char(char *what){
+STRING *string_from_char(const char *what){
STRING *ptr;
int len=strlen(what);
ptr=malloc(4 + len);