const char *nt_errstr(NTSTATUS nt_code) { int idx = 0; char *result; #ifdef HAVE_LDAP if (NT_STATUS_IS_LDAP(nt_code)) { return ldap_err2string(NT_STATUS_LDAP_CODE(nt_code)); } #endif if (NT_STATUS_IS_DOS(nt_code)) { return smb_dos_err_name(NT_STATUS_DOS_CLASS(nt_code), NT_STATUS_DOS_CODE(nt_code)); } while (nt_errs[idx].nt_errstr != NULL) { if (NT_STATUS_EQUAL(nt_errs[idx].nt_errcode, nt_code)) { return nt_errs[idx].nt_errstr; } idx++; } result = talloc_asprintf(talloc_tos(), "NT code 0x%08x", NT_STATUS_V(nt_code)); SMB_ASSERT(result != NULL); return result; }
NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint8_t trans_cmd, const char *pipe_name, uint16_t fid, uint16_t function, int flags, uint16_t *setup, uint8_t num_setup, uint8_t max_setup, uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data, uint16_t *recv_flags2, uint16_t **rsetup, uint8_t min_rsetup, uint8_t *num_rsetup, uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam, uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata) { NTSTATUS status; uint8_t additional_flags = 0; uint8_t clear_flags = 0; uint16_t additional_flags2 = 0; uint16_t clear_flags2 = 0; status = smb1cli_trans(mem_ctx, cli->conn, trans_cmd, additional_flags, clear_flags, additional_flags2, clear_flags2, cli->timeout, cli->smb1.pid, cli->smb1.tcon, cli->smb1.session, pipe_name, fid, function, flags, setup, num_setup, max_setup, param, num_param, max_param, data, num_data, max_data, recv_flags2, rsetup, min_rsetup, num_rsetup, rparam, min_rparam, num_rparam, rdata, min_rdata, num_rdata); cli->raw_status = status; if (NT_STATUS_IS_DOS(status) && cli->map_dos_errors) { uint8_t eclass = NT_STATUS_DOS_CLASS(status); uint16_t ecode = NT_STATUS_DOS_CODE(status); /* * TODO: is it really a good idea to do a mapping here? * * The old cli_pull_error() also does it, so I do not change * the behavior yet. */ status = dos_to_ntstatus(eclass, ecode); } return status; }
NTSTATUS cli_nt_error(struct cli_state *cli) { /* Deal with socket errors first. */ if (!cli_state_is_connected(cli)) { return NT_STATUS_CONNECTION_DISCONNECTED; } if (NT_STATUS_IS_DOS(cli->raw_status)) { int e_class = NT_STATUS_DOS_CLASS(cli->raw_status); int code = NT_STATUS_DOS_CODE(cli->raw_status); return dos_to_ntstatus(e_class, code); } return cli->raw_status; }
void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode) { if (!cli_state_is_connected(cli)) { *eclass = ERRDOS; *ecode = ERRnotconnected; return; } if (!NT_STATUS_IS_DOS(cli->raw_status)) { ntstatus_to_dos(cli->raw_status, eclass, ecode); return; } *eclass = NT_STATUS_DOS_CLASS(cli->raw_status); *ecode = NT_STATUS_DOS_CODE(cli->raw_status); }
void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { BOOL force_nt_status = False; BOOL force_dos_status = False; if (eclass == (uint8)-1) { force_nt_status = True; } else if (NT_STATUS_IS_DOS(ntstatus)) { force_dos_status = True; } if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) { /* We're returning an NT error. */ if (NT_STATUS_V(ntstatus) == 0 && eclass) { ntstatus = dos_to_ntstatus(eclass, ecode); } SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n", file, line, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), nt_errstr(ntstatus))); } else { /* We're returning a DOS error only. */ if (NT_STATUS_IS_DOS(ntstatus)) { eclass = NT_STATUS_DOS_CLASS(ntstatus); ecode = NT_STATUS_DOS_CODE(ntstatus); } else if (eclass == 0 && NT_STATUS_V(ntstatus)) { ntstatus_to_dos(ntstatus, &eclass, &ecode); } SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); SSVAL(outbuf,smb_rcls,eclass); SSVAL(outbuf,smb_err,ecode); DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", file, line, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), eclass, ecode)); } }
NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint16_t *recv_flags2, uint16_t **setup, uint8_t min_setup, uint8_t *num_setup, uint8_t **param, uint32_t min_param, uint32_t *num_param, uint8_t **data, uint32_t min_data, uint32_t *num_data) { NTSTATUS status; void *parent = talloc_parent(req); struct cli_trans_state *state = talloc_get_type(parent, struct cli_trans_state); bool map_dos_errors = true; status = smb1cli_trans_recv(req, mem_ctx, recv_flags2, setup, min_setup, num_setup, param, min_param, num_param, data, min_data, num_data); if (state) { map_dos_errors = state->cli->map_dos_errors; state->cli->raw_status = status; talloc_free(state->ptr); state = NULL; } if (NT_STATUS_IS_DOS(status) && map_dos_errors) { uint8_t eclass = NT_STATUS_DOS_CLASS(status); uint16_t ecode = NT_STATUS_DOS_CODE(status); /* * TODO: is it really a good idea to do a mapping here? * * The old cli_pull_error() also does it, so I do not change * the behavior yet. */ status = dos_to_ntstatus(eclass, ecode); } return status; }
/* setup the header of a reply to include an NTSTATUS code */ void smbsrv_setup_error(struct smbsrv_request *req, NTSTATUS status) { if (!req->smb_conn->config.nt_status_support || !(req->smb_conn->negotiate.client_caps & CAP_STATUS32)) { /* convert to DOS error codes */ uint8_t eclass; uint32_t ecode; ntstatus_to_dos(status, &eclass, &ecode); SCVAL(req->out.hdr, HDR_RCLS, eclass); SSVAL(req->out.hdr, HDR_ERR, ecode); SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES); return; } if (NT_STATUS_IS_DOS(status)) { /* its a encoded DOS error, using the reserved range */ SSVAL(req->out.hdr, HDR_RCLS, NT_STATUS_DOS_CLASS(status)); SSVAL(req->out.hdr, HDR_ERR, NT_STATUS_DOS_CODE(status)); SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES); } else { SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status)); SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES); } }