diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2008-11-24 18:05:55 +0000 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2008-11-24 18:05:55 +0000 |
commit | f7700f2bc2f2d5876c91bbbf3eaae233ee1548b1 (patch) | |
tree | 5e80eb3b78683d183d47759582f9712e23bf84b6 /libssh | |
parent | f880011d727e598561fe64a805a2fb22a39ffcee (diff) | |
download | libssh-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.c | 63 | ||||
-rw-r--r-- | libssh/dh.c | 2 | ||||
-rw-r--r-- | libssh/error.c | 2 | ||||
-rw-r--r-- | libssh/kex.c | 18 | ||||
-rw-r--r-- | libssh/options.c | 18 | ||||
-rw-r--r-- | libssh/session.c | 1 | ||||
-rw-r--r-- | libssh/sftp.c | 189 | ||||
-rw-r--r-- | libssh/string.c | 4 |
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); |