diff --git a/src/sbbs3/sftp.cpp b/src/sbbs3/sftp.cpp index 6a298235bf29f79e1f2fe82cb2d39112cc57d811..069d768c9b90beb2b24a95bdadccbbf360ee8200 100644 --- a/src/sbbs3/sftp.cpp +++ b/src/sbbs3/sftp.cpp @@ -1248,17 +1248,28 @@ sftp_send(uint8_t *buf, size_t len, void *cb_data) } static void -sftp_lprintf(void *arg, const char *fmt, ...) +sftp_lprintf(void *arg, uint32_t errcode, const char *fmt, ...) { sbbs_t *sbbs = (sbbs_t *)arg; va_list argptr; char sbuf[1024]; + int level = LOG_DEBUG; + + switch (errcode) { + case SSH_FX_PERMISSION_DENIED: + level = LOG_INFO; + break; + case SSH_FX_FAILURE: + case SSH_FX_BAD_MESSAGE: + level = LOG_WARNING; + break; + } va_start(argptr,fmt); vsnprintf(sbuf,sizeof(sbuf),fmt,argptr); sbuf[sizeof(sbuf)-1]=0; va_end(argptr); - sbbs->lprintf(LOG_ERR, "SFTP %s", sbuf); + sbbs->lprintf(level, "SFTP error code %" PRIu32 " (%s) %s", errcode, sftp_get_errcode_name(errcode), sbuf); } static void diff --git a/src/sftp/sftp.h b/src/sftp/sftp.h index 172d0f26f39fe8ed549489d858d7d59ca6af29c1..09d1da4bc3ad23b04dd200f0bf5f174d81e6aeed 100644 --- a/src/sftp/sftp.h +++ b/src/sftp/sftp.h @@ -193,7 +193,7 @@ typedef struct sftp_server_state { sftp_rx_pkt_t rxp; sftp_tx_pkt_t txp; void *cb_data; - void (*lprintf)(void *cb_data, const char *fmt, ...); + void (*lprintf)(void *cb_data, uint32_t errcode, const char *fmt, ...); void (*cleanup_callback)(void *cb_data); bool (*open)(sftp_str_t filename, uint32_t flags, sftp_file_attr_t attributes, void *cb_data); bool (*close)(sftp_str_t handle, void *cb_data); @@ -223,6 +223,7 @@ typedef struct sftp_server_state { /* sftp_pkt.c */ const char * const sftp_get_type_name(uint8_t type); +const char * const sftp_get_errcode_name(uint32_t errcode); bool sftp_have_pkt_sz(sftp_rx_pkt_t pkt); bool sftp_have_pkt_type(sftp_rx_pkt_t pkt); uint32_t sftp_pkt_sz(sftp_rx_pkt_t pkt); diff --git a/src/sftp/sftp_pkt.c b/src/sftp/sftp_pkt.c index e65ea0a17ba4c665ae22d9f1d054f494d7cd918c..7f15fd797a00dda0e9462b2c4f0abee2f4cac01e 100644 --- a/src/sftp/sftp_pkt.c +++ b/src/sftp/sftp_pkt.c @@ -45,6 +45,21 @@ static const struct type_names { }; static const char * const notfound_type = "<UNKNOWN>"; +static const struct errcode_names { + const uint32_t errcode; + const char * const name; +} errcode_names[] = { + {SSH_FX_OK, "OK"}, + {SSH_FX_EOF, "End Of File"}, + {SSH_FX_NO_SUCH_FILE, "No Such File"}, + {SSH_FX_PERMISSION_DENIED, "Permission Denied"}, + {SSH_FX_FAILURE, "General Failure"}, + {SSH_FX_BAD_MESSAGE, "Bad Message"}, + {SSH_FX_NO_CONNECTION, "No Connection"}, + {SSH_FX_CONNECTION_LOST, "Connection Lost"}, + {SSH_FX_OP_UNSUPPORTED, "Operation Unsupported"}, +}; + static int type_cmp(const void *key, const void *name) { int k = *(uint8_t *)key; @@ -63,6 +78,24 @@ sftp_get_type_name(uint8_t type) return t->name; } +static int errcode_cmp(const void *key, const void *name) +{ + int k = *(uint32_t *)key; + int n = *(uint32_t *)name; + + return k - n; +} + +const char * const +sftp_get_errcode_name(uint32_t errcode) +{ + struct errcode_names *ec = (struct errcode_names *)(bsearch(&errcode, errcode_names, sizeof(errcode_names) / sizeof(errcode_names[0]), sizeof(errcode_names[0]), errcode_cmp)); + + if (ec == NULL) + return notfound_type; + return ec->name; +} + bool sftp_have_pkt_sz(sftp_rx_pkt_t pkt) { diff --git a/src/sftp/sftp_server.c b/src/sftp/sftp_server.c index 1d047b22a36c9f117fe63df0a4ea075f1f6270e8..d4ee26aaf2696c1a2901787c4e6475523329fe39 100644 --- a/src/sftp/sftp_server.c +++ b/src/sftp/sftp_server.c @@ -329,6 +329,8 @@ sftps_send_packet(sftps_state_t state) bool sftps_send_error(sftps_state_t state, uint32_t code, const char *msg) { + if (state->lprintf) + state->lprintf(state->cb_data, code, "%s", msg); if (!appendheader(state, SSH_FXP_STATUS)) return false; if (!append32(state, code)) @@ -373,7 +375,8 @@ sftps_recv(sftps_state_t state, uint8_t *buf, uint32_t sz) if (sftp_have_pkt_sz(state->rxp)) { uint32_t psz = sftp_pkt_sz(state->rxp); if (psz > SFTP_MAX_PACKET_SIZE) { - state->lprintf(state->cb_data, "Packet too large (%" PRIu32 " bytes)", psz); + if (state->lprintf) + state->lprintf(state->cb_data, SSH_FX_FAILURE, "Packet too large (%" PRIu32 " bytes)", psz); return exit_function(state, false); } } @@ -526,7 +529,7 @@ sftps_recv(sftps_state_t state, uint8_t *buf, uint32_t sz) } if (!handled) { if (state->lprintf) - state->lprintf(state->cb_data, "Unhandled request type: %s (%d)", sftp_get_type_name(state->rxp->type), state->rxp->type); + state->lprintf(state->cb_data, SSH_FX_FAILURE, "Unhandled request type: %s (%d)", sftp_get_type_name(state->rxp->type), state->rxp->type); state->id = get32(state); if (!sftps_send_error(state, SSH_FX_OP_UNSUPPORTED, "Operation not implemented")) return exit_function(state, false); @@ -565,19 +568,22 @@ sftps_send_name(sftps_state_t state, uint32_t count, str_list_t fnames, str_list return false; for (uint32_t idx = 0; idx < count; idx++) { if (fnames[idx] == NULL) { - state->lprintf(state->cb_data, "Reached fnames terminator at position %" PRIu32 " of " PRIu32, idx, count); + if (state->lprintf) + state->lprintf(state->cb_data, SSH_FX_FAILURE, "Reached fnames terminator at position %" PRIu32 " of " PRIu32, idx, count); return false; } if (!appendcstring(state, fnames[idx])) return false; if (lnames[idx] == NULL) { - state->lprintf(state->cb_data, "Reached lnames terminator at position %" PRIu32 " of " PRIu32, idx, count); + if (state->lprintf) + state->lprintf(state->cb_data, SSH_FX_FAILURE, "Reached lnames terminator at position %" PRIu32 " of " PRIu32, idx, count); return false; } if (!appendcstring(state, lnames[idx])) return false; if (attrs[idx] == NULL) { - state->lprintf(state->cb_data, "Reached attrs terminator at position %" PRIu32 " of " PRIu32, idx, count); + if (state->lprintf) + state->lprintf(state->cb_data, SSH_FX_FAILURE, "Reached attrs terminator at position %" PRIu32 " of " PRIu32, idx, count); return false; } if (!appendfattr(state, attrs[idx]))