bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status) { char *q = prs_mem_get(ps, sizeof(uint32)); if (q == NULL) return False; if (UNMARSHALLING(ps)) { if (ps->bigendian_data) *status = NT_STATUS(RIVAL(q,0)); else *status = NT_STATUS(IVAL(q,0)); } else { if (ps->bigendian_data) RSIVAL(q,0,NT_STATUS_V(*status)); else SIVAL(q,0,NT_STATUS_V(*status)); } DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, dcerpc_errstr(talloc_tos(), NT_STATUS_V(*status)))); ps->data_offset += sizeof(uint32); return True; }
BOOL prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status) { char *q = prs_mem_get(ps, sizeof(uint32)); if (q == NULL) return False; if (UNMARSHALLING(ps)) { if (ps->bigendian_data) *status = NT_STATUS(RIVAL(q,0)); else *status = NT_STATUS(IVAL(q,0)); } else { if (ps->bigendian_data) RSIVAL(q,0,NT_STATUS_V(*status)); else SIVAL(q,0,NT_STATUS_V(*status)); } DEBUG(5,("%s%04x %s: %s\n", tab_depth(depth), ps->data_offset, name, get_nt_error_msg(*status))); ps->data_offset += sizeof(uint32); return True; }
static bool torture_winbind_struct_check_machacc(struct torture_context *torture) { bool ok; bool strict = torture_setting_bool(torture, "strict mode", false); struct winbindd_response rep; ZERO_STRUCT(rep); torture_comment(torture, "Running WINBINDD_CHECK_MACHACC (struct based)\n"); ok = true; DO_STRUCT_REQ_REP_EXT(WINBINDD_CHECK_MACHACC, NULL, &rep, NSS_STATUS_SUCCESS, strict, ok = false, "WINBINDD_CHECK_MACHACC"); if (!ok) { torture_assert(torture, strlen(rep.data.auth.nt_status_string)>0, "Failed with empty nt_status_string"); torture_warning(torture,"%s:%s:%s:%d\n", nt_errstr(NT_STATUS(rep.data.auth.nt_status)), rep.data.auth.nt_status_string, rep.data.auth.error_string, rep.data.auth.pam_error); return true; } torture_assert_ntstatus_ok(torture, NT_STATUS(rep.data.auth.nt_status), "WINBINDD_CHECK_MACHACC ok: nt_status"); torture_assert_str_equal(torture, rep.data.auth.nt_status_string, nt_errstr(NT_STATUS_OK), "WINBINDD_CHECK_MACHACC ok:nt_status_string"); torture_assert_str_equal(torture, rep.data.auth.error_string, get_friendly_nt_error_msg(NT_STATUS_OK), "WINBINDD_CHECK_MACHACC ok: error_string"); torture_assert_int_equal(torture, rep.data.auth.pam_error, nt_status_to_pam(NT_STATUS_OK), "WINBINDD_CHECK_MACHACC ok: pam_error"); return true; }
static bool api_spoolss_addprinterdriver(pipes_struct *p) { SPOOL_Q_ADDPRINTERDRIVER q_u; SPOOL_R_ADDPRINTERDRIVER r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); if(!spoolss_io_q_addprinterdriver("", &q_u, data, 0)) { if (q_u.level != 3 && q_u.level != 6) { /* Clever hack from Martin Zielinski <*****@*****.**> * to allow downgrade from level 8 (Vista). */ DEBUG(3,("api_spoolss_addprinterdriver: unknown SPOOL_Q_ADDPRINTERDRIVER level %u.\n", (unsigned int)q_u.level )); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_INVALID_TAG)); return True; } DEBUG(0,("spoolss_io_q_addprinterdriver: unable to unmarshall SPOOL_Q_ADDPRINTERDRIVER.\n")); return False; } r_u.status = _spoolss_addprinterdriver(p, &q_u, &r_u); if(!spoolss_io_r_addprinterdriver("", &r_u, rdata, 0)) { DEBUG(0,("spoolss_io_r_addprinterdriver: unable to marshall SPOOL_R_ADDPRINTERDRIVER.\n")); return False; } return True; }
bool create_next_pdu(struct pipes_struct *p) { size_t pdu_size = 0; NTSTATUS status; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if (p->fault_state) { setup_fault_pdu(p, NT_STATUS(p->fault_state)); return true; } status = create_next_packet(p->mem_ctx, &p->auth, p->call_id, &p->out_data.rdata, p->out_data.data_sent_length, &p->out_data.frag, &pdu_size); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to create packet with error %s, " "(auth level %u / type %u)\n", nt_errstr(status), (unsigned int)p->auth.auth_level, (unsigned int)p->auth.auth_type)); return false; } /* Setup the counts for this PDU. */ p->out_data.data_sent_length += pdu_size; p->out_data.current_pdu_sent = 0; return true; }
static BOOL api_samr_set_userinfo(pipes_struct *p) { SAMR_Q_SET_USERINFO q_u; SAMR_R_SET_USERINFO r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); if (!samr_io_q_set_userinfo("", &q_u, data, 0)) { DEBUG(0,("api_samr_set_userinfo: Unable to unmarshall SAMR_Q_SET_USERINFO.\n")); /* Fix for W2K SP2 */ /* what is that status-code ? - gd */ if (q_u.switch_value == 0x1a) { setup_fault_pdu(p, NT_STATUS(0x1c000006)); return True; } return False; } r_u.status = _samr_set_userinfo(p, &q_u, &r_u); if(!samr_io_r_set_userinfo("", &r_u, rdata, 0)) { DEBUG(0,("api_samr_set_userinfo: Unable to marshall SAMR_R_SET_USERINFO.\n")); return False; } return True; }
static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; fstring user; long error_num; DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); fstrcpy(user, user_info->client.account_name); if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) { if (!strupper_m(user)) { return NT_STATUS_INVALID_PARAMETER; } return nt_status_string_to_code(user); } if (!strlower_m(user)) { return NT_STATUS_INVALID_PARAMETER; } error_num = strtoul(user, NULL, 16); DEBUG(5,("check_name_to_ntstatus_security: Error for user %s was %lx\n", user, error_num)); nt_status = NT_STATUS(error_num); return nt_status; }
static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { NTSTATUS nt_status; fstring user; long error_num; fstrcpy(user, user_info->smb_name); if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) { strupper_m(user); return nt_status_string_to_code(user); } strlower_m(user); error_num = strtoul(user, NULL, 16); DEBUG(5,("check_name_to_ntstatus_security: Error for user %s was %lx\n", user, error_num)); nt_status = NT_STATUS(error_num); return nt_status; }
void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode) { int flgs2; if(!cli->initialised) { return; } /* Deal with socket errors first. */ if (cli->fd == -1 && cli->smb_rw_error) { NTSTATUS status = cli_smb_rw_error_to_ntstatus(cli); ntstatus_to_dos( status, eclass, ecode); return; } flgs2 = SVAL(cli->inbuf,smb_flg2); if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { NTSTATUS ntstatus = NT_STATUS(IVAL(cli->inbuf, smb_rcls)); ntstatus_to_dos(ntstatus, eclass, ecode); return; } *eclass = CVAL(cli->inbuf,smb_rcls); *ecode = SVAL(cli->inbuf,smb_err); }
/* pull a NTSTATUS */ _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status) { uint32_t v; NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v)); *status = NT_STATUS(v); return NDR_ERR_SUCCESS; }
const char *libnetapi_errstr(NET_API_STATUS status) { if (status & 0xc0000000) { return get_friendly_nt_error_msg(NT_STATUS(status)); } return get_friendly_werror_msg(W_ERROR(status)); }
static NTSTATUS rpcint_dispatch(struct pipes_struct *p, TALLOC_CTX *mem_ctx, uint32_t opnum, const DATA_BLOB *in_data, DATA_BLOB *out_data) { struct pipe_rpc_fns *fns = find_pipe_fns_by_context(p->contexts, 0); uint32_t num_cmds = fns->n_cmds; const struct api_struct *cmds = fns->cmds; uint32_t i; bool ok; /* set opnum */ p->opnum = opnum; for (i = 0; i < num_cmds; i++) { if (cmds[i].opnum == opnum && cmds[i].fn != NULL) { break; } } if (i == num_cmds) { return NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE; } p->in_data.data = *in_data; p->out_data.rdata = data_blob_null; ok = cmds[i].fn(p); p->in_data.data = data_blob_null; if (!ok) { data_blob_free(&p->out_data.rdata); talloc_free_children(p->mem_ctx); return NT_STATUS_RPC_CALL_FAILED; } if (p->fault_state) { NTSTATUS status; status = NT_STATUS(p->fault_state); p->fault_state = 0; data_blob_free(&p->out_data.rdata); talloc_free_children(p->mem_ctx); return status; } *out_data = p->out_data.rdata; talloc_steal(mem_ctx, out_data->data); p->out_data.rdata = data_blob_null; talloc_free_children(p->mem_ctx); return NT_STATUS_OK; }
static BOOL cli_dfs_check_error( struct cli_state *cli, NTSTATUS status ) { uint32 flgs2 = SVAL(cli->inbuf,smb_flg2); /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */ if ( !( (flgs2&FLAGS2_32_BIT_ERROR_CODES) && (flgs2&FLAGS2_UNICODE_STRINGS) ) ) return False; if ( NT_STATUS_EQUAL( status, NT_STATUS(IVAL(cli->inbuf,smb_rcls)) ) ) return True; return False; }
char *libnetapi_errstr(NET_API_STATUS status) { TALLOC_CTX *frame = talloc_stackframe(); char *ret; if (status & 0xc0000000) { ret = talloc_strdup(NULL, get_friendly_nt_error_msg(NT_STATUS(status))); } else { ret = talloc_strdup(NULL, get_friendly_werror_msg(W_ERROR(status))); } TALLOC_FREE(frame); return ret; }
NTSTATUS cli_nt_error(struct cli_state *cli) { int flgs2 = SVAL(cli->inbuf,smb_flg2); /* Deal with socket errors first. */ if (cli->fd == -1 && cli->smb_rw_error) { return cli_smb_rw_error_to_ntstatus(cli); } if (!(flgs2 & FLAGS2_32_BIT_ERROR_CODES)) { int e_class = CVAL(cli->inbuf,smb_rcls); int code = SVAL(cli->inbuf,smb_err); return dos_to_ntstatus(e_class, code); } return NT_STATUS(IVAL(cli->inbuf,smb_rcls)); }
bool srv_check_sign_mac(struct smbd_server_connection *conn, const char *inbuf, uint32_t *seqnum, bool trusted_channel) { const uint8_t *inhdr; size_t len; /* Check if it's a non-session message. */ if(CVAL(inbuf,0)) { return true; } len = smb_len(inbuf); inhdr = (const uint8_t *)inbuf + NBT_HDR_SIZE; if (trusted_channel) { NTSTATUS status; if (len < (HDR_SS_FIELD + 8)) { DEBUG(1,("smb_signing_check_pdu: Can't check signature " "on short packet! smb_len = %u\n", (unsigned)len)); return false; } status = NT_STATUS(IVAL(inhdr, HDR_SS_FIELD + 4)); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n", nt_errstr(status))); return false; } *seqnum = IVAL(inhdr, HDR_SS_FIELD); return true; } *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false); return smb_signing_check_pdu(conn->smb1.signing_state, inhdr, len, *seqnum); }
bool tevent_req_is_nterror(struct tevent_req *req, NTSTATUS *status) { enum tevent_req_state state; uint64_t err; if (!tevent_req_is_error(req, &state, &err)) { return false; } switch (state) { case TEVENT_REQ_TIMED_OUT: *status = NT_STATUS_IO_TIMEOUT; break; case TEVENT_REQ_NO_MEMORY: *status = NT_STATUS_NO_MEMORY; break; case TEVENT_REQ_USER_ERROR: *status = NT_STATUS(err); break; default: *status = NT_STATUS_INTERNAL_ERROR; break; } return true; }
{ERRDOS, ERRbadfid, NT_STATUS_INVALID_HANDLE}, {ERRDOS, ERRnomem, NT_STATUS_INSUFFICIENT_RESOURCES}, {ERRDOS, ERRbadaccess, NT_STATUS_ACCESS_DENIED}, {ERRDOS, ERRbaddata, NT_STATUS_DATA_ERROR}, {ERRDOS, 14, NT_STATUS_SECTION_NOT_EXTENDED}, {ERRDOS, ERRremcd, NT_STATUS_DIRECTORY_NOT_EMPTY}, {ERRDOS, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE}, {ERRDOS, ERRnofiles, STATUS_NO_MORE_FILES}, {ERRDOS, 19, NT_STATUS_MEDIA_WRITE_PROTECTED}, {ERRDOS, 21, NT_STATUS_NO_MEDIA_IN_DEVICE}, {ERRDOS, 22, NT_STATUS_INVALID_DEVICE_STATE}, {ERRDOS, 23, NT_STATUS_DATA_ERROR}, {ERRDOS, 24, NT_STATUS_DATA_ERROR}, {ERRDOS, 26, NT_STATUS_DISK_CORRUPT_ERROR}, {ERRDOS, 27, NT_STATUS_NONEXISTENT_SECTOR}, {ERRDOS, 28, NT_STATUS(0x8000000e)}, {ERRDOS, 31, NT_STATUS_UNSUCCESSFUL}, {ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION}, {ERRDOS, ERRlock, NT_STATUS_FILE_LOCK_CONFLICT}, {ERRDOS, 34, NT_STATUS_WRONG_VOLUME}, {ERRDOS, 38, NT_STATUS_END_OF_FILE}, {ERRDOS, ERRunsup, NT_STATUS_CTL_FILE_NOT_SUPPORTED}, {ERRDOS, 51, NT_STATUS_REMOTE_NOT_LISTENING}, {ERRDOS, 52, NT_STATUS_DUPLICATE_NAME}, {ERRDOS, 53, NT_STATUS_BAD_NETWORK_PATH}, {ERRDOS, 54, NT_STATUS_NETWORK_BUSY}, {ERRDOS, 55, NT_STATUS_DEVICE_DOES_NOT_EXIST}, {ERRDOS, 56, NT_STATUS_TOO_MANY_COMMANDS}, {ERRDOS, 57, NT_STATUS_ADAPTER_HARDWARE_ERROR}, {ERRDOS, 58, NT_STATUS_INVALID_NETWORK_RESPONSE}, {ERRDOS, 59, NT_STATUS_UNEXPECTED_NETWORK_ERROR},
static NTSTATUS check_wbc_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; if (!user_info || !auth_context || !server_info) { return NT_STATUS_INVALID_PARAMETER; } /* Send off request */ params.account_name = user_info->smb_name; params.domain_name = user_info->domain; params.workstation_name = user_info->wksta_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; /* Handle plaintext */ if (!user_info->encrypted) { DEBUG(3,("Checking plaintext password for %s.\n", user_info->internal_username)); params.level = WBC_AUTH_USER_LEVEL_PLAIN; params.password.plaintext = (char *)user_info->plaintext_password.data; } else { DEBUG(3,("Checking encrypted password for %s.\n", user_info->internal_username)); params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); params.password.response.nt_length = user_info->nt_resp.length; params.password.response.nt_data = user_info->nt_resp.data; params.password.response.lm_length = user_info->lm_resp.length; params.password.response.lm_data = user_info->lm_resp.data; } /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("wbcAuthenticateUserEx failed (%d): %s\n", wbc_status, wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } DEBUG(10,("wbcAuthenticateUserEx succeeded\n")); nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->smb_name, user_info->domain, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
const char *cli_errstr(struct cli_state *cli) { static fstring cli_error_message; uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), errnum; uint8 errclass; int i; if (!cli->initialised) { fstrcpy(cli_error_message, "[Programmer's error] cli_errstr called on unitialized cli_stat struct!\n"); return cli_error_message; } /* Was it server socket error ? */ if (cli->fd == -1 && cli->smb_rw_error) { switch(cli->smb_rw_error) { case READ_TIMEOUT: slprintf(cli_error_message, sizeof(cli_error_message) - 1, "Call timed out: server did not respond after %d milliseconds", cli->timeout); break; case READ_EOF: slprintf(cli_error_message, sizeof(cli_error_message) - 1, "Call returned zero bytes (EOF)\n" ); break; case READ_ERROR: slprintf(cli_error_message, sizeof(cli_error_message) - 1, "Read error: %s\n", strerror(errno) ); break; case WRITE_ERROR: slprintf(cli_error_message, sizeof(cli_error_message) - 1, "Write error: %s\n", strerror(errno) ); break; default: slprintf(cli_error_message, sizeof(cli_error_message) - 1, "Unknown error code %d\n", cli->smb_rw_error ); break; } return cli_error_message; } /* Case #1: RAP error */ if (cli->rap_error) { for (i = 0; rap_errmap[i].message != NULL; i++) { if (rap_errmap[i].err == cli->rap_error) { return rap_errmap[i].message; } } slprintf(cli_error_message, sizeof(cli_error_message) - 1, "RAP code %d", cli->rap_error); return cli_error_message; } /* Case #2: 32-bit NT errors */ if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { NTSTATUS status = NT_STATUS(IVAL(cli->inbuf,smb_rcls)); return get_nt_error_msg(status); } cli_dos_error(cli, &errclass, &errnum); /* Case #3: SMB error */ return cli_smb_errstr(cli); }
/* we have a full request in our receive buffer - match it to a pending request and process */ static NTSTATUS smbcli_transport_finish_recv(void *private_data, DATA_BLOB blob) { struct smbcli_transport *transport = talloc_get_type(private_data, struct smbcli_transport); uint8_t *buffer, *hdr, *vwv; int len; uint16_t wct=0, mid = 0, op = 0; struct smbcli_request *req = NULL; buffer = blob.data; len = blob.length; hdr = buffer+NBT_HDR_SIZE; vwv = hdr + HDR_VWV; /* see if it could be an oplock break request */ if (smbcli_handle_oplock_break(transport, len, hdr, vwv)) { talloc_free(buffer); return NT_STATUS_OK; } /* at this point we need to check for a readbraw reply, as these can be any length */ if (transport->readbraw_pending) { transport->readbraw_pending = 0; /* it must match the first entry in the pending queue as the client is not allowed to have outstanding readbraw requests */ req = transport->pending_recv; if (!req) goto error; req->in.buffer = buffer; talloc_steal(req, buffer); req->in.size = len; req->in.allocated = req->in.size; goto async; } if (len >= MIN_SMB_SIZE) { /* extract the mid for matching to pending requests */ mid = SVAL(hdr, HDR_MID); wct = CVAL(hdr, HDR_WCT); op = CVAL(hdr, HDR_COM); } /* match the incoming request against the list of pending requests */ for (req=transport->pending_recv; req; req=req->next) { if (req->mid == mid) break; } /* see if it's a ntcancel reply for the current MID */ req = smbcli_handle_ntcancel_reply(req, len, hdr); if (!req) { DEBUG(1,("Discarding unmatched reply with mid %d op %d\n", mid, op)); goto error; } /* fill in the 'in' portion of the matching request */ req->in.buffer = buffer; talloc_steal(req, buffer); req->in.size = len; req->in.allocated = req->in.size; /* handle NBT session replies */ if (req->in.size >= 4 && req->in.buffer[0] != 0) { req->status = NT_STATUS_OK; goto async; } /* handle non-SMB replies */ if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE) { req->state = SMBCLI_REQUEST_ERROR; goto error; } if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) { DEBUG(2,("bad reply size for mid %d\n", mid)); req->status = NT_STATUS_UNSUCCESSFUL; req->state = SMBCLI_REQUEST_ERROR; goto error; } req->in.hdr = hdr; req->in.vwv = vwv; req->in.wct = wct; if (req->in.size >= NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)) { req->in.data = req->in.vwv + VWV(wct) + 2; req->in.data_size = SVAL(req->in.vwv, VWV(wct)); if (req->in.size < NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct) + req->in.data_size) { DEBUG(3,("bad data size for mid %d\n", mid)); /* blergh - w2k3 gives a bogus data size values in some openX replies */ req->in.data_size = req->in.size - (NBT_HDR_SIZE + MIN_SMB_SIZE + VWV(wct)); } } req->in.ptr = req->in.data; req->flags2 = SVAL(req->in.hdr, HDR_FLG2); smb_setup_bufinfo(req); if (!(req->flags2 & FLAGS2_32_BIT_ERROR_CODES)) { int eclass = CVAL(req->in.hdr,HDR_RCLS); int code = SVAL(req->in.hdr,HDR_ERR); if (eclass == 0 && code == 0) { transport->error.e.nt_status = NT_STATUS_OK; } else { transport->error.e.nt_status = NT_STATUS_DOS(eclass, code); } } else { transport->error.e.nt_status = NT_STATUS(IVAL(req->in.hdr, HDR_RCLS)); } req->status = transport->error.e.nt_status; if (NT_STATUS_IS_OK(req->status)) { transport->error.etype = ETYPE_NONE; } else { transport->error.etype = ETYPE_SMB; } if (!smbcli_request_check_sign_mac(req)) { transport->error.etype = ETYPE_SOCKET; transport->error.e.socket_error = SOCKET_READ_BAD_SIG; req->state = SMBCLI_REQUEST_ERROR; req->status = NT_STATUS_ACCESS_DENIED; goto error; }; async: /* if this request has an async handler then call that to notify that the reply has been received. This might destroy the request so it must happen last */ req->state = SMBCLI_REQUEST_DONE; if (req->recv_helper.fn) { /* * let the recv helper decide in * what state the request really is */ req->state = req->recv_helper.fn(req); /* if more parts are needed, wait for them */ if (req->state <= SMBCLI_REQUEST_RECV) { return NT_STATUS_OK; } } DLIST_REMOVE(transport->pending_recv, req); if (req->async.fn) { req->async.fn(req); } return NT_STATUS_OK; error: if (req) { DLIST_REMOVE(transport->pending_recv, req); req->state = SMBCLI_REQUEST_ERROR; if (req->async.fn) { req->async.fn(req); } } else { talloc_free(buffer); } return NT_STATUS_OK; }
static bool srv_pipe_check_verification_trailer(struct pipes_struct *p, struct ncacn_packet *pkt, struct pipe_rpc_fns *pipe_fns) { TALLOC_CTX *frame = talloc_stackframe(); struct dcerpc_sec_verification_trailer *vt = NULL; const uint32_t bitmask1 = p->auth.client_hdr_signing ? DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0; const struct dcerpc_sec_vt_pcontext pcontext = { .abstract_syntax = pipe_fns->syntax, .transfer_syntax = ndr_transfer_syntax_ndr, }; const struct dcerpc_sec_vt_header2 header2 = dcerpc_sec_vt_header2_from_ncacn_packet(pkt); struct ndr_pull *ndr; enum ndr_err_code ndr_err; bool ret = false; ndr = ndr_pull_init_blob(&p->in_data.data, frame); if (ndr == NULL) { goto done; } ndr_err = ndr_pop_dcerpc_sec_verification_trailer(ndr, frame, &vt); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { goto done; } ret = dcerpc_sec_verification_trailer_check(vt, &bitmask1, &pcontext, &header2); done: TALLOC_FREE(frame); return ret; } /**************************************************************************** Find the correct RPC function to call for this request. If the pipe is authenticated then become the correct UNIX user before doing the call. ****************************************************************************/ static bool api_pipe_request(struct pipes_struct *p, struct ncacn_packet *pkt) { TALLOC_CTX *frame = talloc_stackframe(); bool ret = False; struct pipe_rpc_fns *pipe_fns; if (!p->pipe_bound) { DEBUG(1, ("Pipe not bound!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } /* get the set of RPC functions for this context */ pipe_fns = find_pipe_fns_by_context(p->contexts, pkt->u.request.context_id); if (pipe_fns == NULL) { DEBUG(0, ("No rpc function table associated with context " "[%d]\n", pkt->u.request.context_id)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } if (!srv_pipe_check_verification_trailer(p, pkt, pipe_fns)) { DEBUG(1, ("srv_pipe_check_verification_trailer: failed\n")); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_ACCESS_DENIED)); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return true; } if (!become_authenticated_pipe_user(p->session_info)) { DEBUG(1, ("Failed to become pipe user!\n")); data_blob_free(&p->out_data.rdata); TALLOC_FREE(frame); return false; } DEBUG(5, ("Requested %s rpc service\n", ndr_interface_name(&pipe_fns->syntax.uuid, pipe_fns->syntax.if_version))); ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds, &pipe_fns->syntax); unbecome_authenticated_pipe_user(); TALLOC_FREE(frame); return ret; }
{NT_STATUS_PORT_MESSAGE_TOO_LONG, EMSGSIZE}, {NT_STATUS_PROTOCOL_UNREACHABLE, ENOPROTOOPT}, {NT_STATUS_ADDRESS_ALREADY_EXISTS, EADDRINUSE}, {NT_STATUS_PORT_UNREACHABLE, EHOSTUNREACH}, {NT_STATUS_IO_TIMEOUT, ETIMEDOUT}, {NT_STATUS_RETRY, EAGAIN}, #ifdef ENOTUNIQ {NT_STATUS_DUPLICATE_NAME, ENOTUNIQ}, #endif #ifdef ECOMM {NT_STATUS_NET_WRITE_FAULT, ECOMM}, #endif #ifdef EXDEV {NT_STATUS_NOT_SAME_DEVICE, EXDEV}, #endif {NT_STATUS(0), 0} }; int map_errno_from_nt_status(NTSTATUS status) { int i; DEBUG(10,("map_errno_from_nt_status: 32 bit codes: code=%08x\n", NT_STATUS_V(status))); /* Status codes without this bit set are not errors */ if (!(NT_STATUS_V(status) & 0xc0000000)) { return 0; } for (i=0;nt_errno_map[i].error;i++) {
static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt, const struct api_struct *api_rpc_cmds, int n_cmds, const struct ndr_syntax_id *syntax) { int fn_num; uint32_t offset1; const struct ndr_interface_table *table; /* interpret the command */ DEBUG(4,("api_rpcTNP: %s op 0x%x - ", ndr_interface_name(&syntax->uuid, syntax->if_version), pkt->u.request.opnum)); table = ndr_table_by_uuid(&syntax->uuid); if (table == NULL) { DEBUG(0,("unknown interface\n")); return false; } if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "in_%s", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->in_data.data, 0, p->in_data.data.length); } for (fn_num = 0; fn_num < n_cmds; fn_num++) { if (api_rpc_cmds[fn_num].opnum == pkt->u.request.opnum && api_rpc_cmds[fn_num].fn != NULL) { DEBUG(3, ("api_rpcTNP: rpc command: %s\n", api_rpc_cmds[fn_num].name)); break; } } if (fn_num == n_cmds) { /* * For an unknown RPC just return a fault PDU but * return True to allow RPC's on the pipe to continue * and not put the pipe into fault state. JRA. */ DEBUG(4, ("unknown\n")); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return True; } offset1 = p->out_data.rdata.length; DEBUG(6, ("api_rpc_cmds[%d].fn == %p\n", fn_num, api_rpc_cmds[fn_num].fn)); /* do the actual command */ if(!api_rpc_cmds[fn_num].fn(p)) { DEBUG(0,("api_rpcTNP: %s: %s failed.\n", ndr_interface_name(&syntax->uuid, syntax->if_version), api_rpc_cmds[fn_num].name)); data_blob_free(&p->out_data.rdata); return False; } if (p->fault_state) { DEBUG(4,("api_rpcTNP: fault(%d) return.\n", p->fault_state)); setup_fault_pdu(p, NT_STATUS(p->fault_state)); p->fault_state = 0; return true; } if (DEBUGLEVEL >= 50) { fstring name; slprintf(name, sizeof(name)-1, "out_%s", dcerpc_default_transport_endpoint(pkt, NCACN_NP, table)); dump_pdu_region(name, pkt->u.request.opnum, &p->out_data.rdata, offset1, p->out_data.rdata.length); } DEBUG(5,("api_rpcTNP: called %s successfully\n", ndr_interface_name(&syntax->uuid, syntax->if_version))); /* Check for buffer underflow in rpc parsing */ if ((DEBUGLEVEL >= 10) && (pkt->frag_length < p->in_data.data.length)) { DEBUG(10, ("api_rpcTNP: rpc input buffer underflow (parse error?)\n")); dump_data(10, p->in_data.data.data + pkt->frag_length, p->in_data.data.length - pkt->frag_length); } return True; }
static void process_complete_pdu(pipes_struct *p) { prs_struct rpc_in; size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN; char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN]; bool reply = False; if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return; } prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL); /* * Ensure we're using the corrent endianness for both the * RPC header flags and the raw data we will be reading from. */ prs_set_endian_data( &rpc_in, p->endian); prs_set_endian_data( &p->in_data.data, p->endian); prs_give_memory( &rpc_in, data_p, (uint32)data_len, False); DEBUG(10,("process_complete_pdu: processing packet type %u\n", (unsigned int)p->hdr.pkt_type )); switch (p->hdr.pkt_type) { case RPC_REQUEST: reply = process_request_pdu(p, &rpc_in); break; case RPC_PING: /* CL request - ignore... */ DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_RESPONSE: /* No responses here. */ DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_FAULT: case RPC_WORKING: /* CL request - reply to a ping when a call in process. */ case RPC_NOCALL: /* CL - server reply to a ping call. */ case RPC_REJECT: case RPC_ACK: case RPC_CL_CANCEL: case RPC_FACK: case RPC_CANCEL_ACK: DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_BIND: /* * We assume that a pipe bind is only in one pdu. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_bind_req(p, &rpc_in); } break; case RPC_BINDACK: case RPC_BINDNACK: DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_ALTCONT: /* * We assume that a pipe bind is only in one pdu. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_alter_context(p, &rpc_in); } break; case RPC_ALTCONTRESP: DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_AUTH3: /* * The third packet in an NTLMSSP auth exchange. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_bind_auth3(p, &rpc_in); } break; case RPC_SHUTDOWN: DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_CO_CANCEL: /* For now just free all client data and continue processing. */ DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); /* As we never do asynchronous RPC serving, we can never cancel a call (as far as I know). If we ever did we'd have to send a cancel_ack reply. For now, just free all client data and continue processing. */ reply = True; break; #if 0 /* Enable this if we're doing async rpc. */ /* We must check the call-id matches the outstanding callid. */ if(pipe_init_outgoing_data(p)) { /* Send a cancel_ack PDU reply. */ /* We should probably check the auth-verifier here. */ reply = setup_cancel_ack_reply(p, &rpc_in); } break; #endif case RPC_ORPHANED: /* We should probably check the auth-verifier here. For now just free all client data and continue processing. */ DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); reply = True; break; default: DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type )); break; } /* Reset to little endian. Probably don't need this but it won't hurt. */ prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN); if (!reply) { DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); prs_mem_free(&rpc_in); } else { /* * Reset the lengths. We're ready for a new pdu. */ TALLOC_FREE(p->in_data.current_in_pdu); p->in_data.pdu_needed_len = 0; p->in_data.pdu_received_len = 0; } prs_mem_free(&rpc_in); }
NTSTATUS contact_winbind_auth_crap(const char *username, const char *domain, const char *workstation, const DATA_BLOB *challenge, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, uint32 flags, uint8 lm_key[8], uint8 user_session_key[16], char **error_string, char **unix_name) { NTSTATUS nt_status; NSS_STATUS result; struct winbindd_request request; struct winbindd_response response; if (!get_require_membership_sid()) { return NT_STATUS_INVALID_PARAMETER; } ZERO_STRUCT(request); ZERO_STRUCT(response); request.flags = flags; request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT; if (require_membership_of_sid) fstrcpy(request.data.auth_crap.require_membership_of_sid, require_membership_of_sid); fstrcpy(request.data.auth_crap.user, username); fstrcpy(request.data.auth_crap.domain, domain); fstrcpy(request.data.auth_crap.workstation, workstation); memcpy(request.data.auth_crap.chal, challenge->data, MIN(challenge->length, 8)); if (lm_response && lm_response->length) { memcpy(request.data.auth_crap.lm_resp, lm_response->data, MIN(lm_response->length, sizeof(request.data.auth_crap.lm_resp))); request.data.auth_crap.lm_resp_len = lm_response->length; } if (nt_response && nt_response->length) { memcpy(request.data.auth_crap.nt_resp, nt_response->data, MIN(nt_response->length, sizeof(request.data.auth_crap.nt_resp))); request.data.auth_crap.nt_resp_len = nt_response->length; } result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response); /* Display response */ if ((result != NSS_STATUS_SUCCESS) && (response.data.auth.nt_status == 0)) { nt_status = NT_STATUS_UNSUCCESSFUL; if (error_string) *error_string = smb_xstrdup("Reading winbind reply failed!"); free_response(&response); return nt_status; } nt_status = (NT_STATUS(response.data.auth.nt_status)); if (!NT_STATUS_IS_OK(nt_status)) { if (error_string) *error_string = smb_xstrdup(response.data.auth.error_string); free_response(&response); return nt_status; } if ((flags & WBFLAG_PAM_LMKEY) && lm_key) { memcpy(lm_key, response.data.auth.first_8_lm_hash, sizeof(response.data.auth.first_8_lm_hash)); } if ((flags & WBFLAG_PAM_USER_SESSION_KEY) && user_session_key) { memcpy(user_session_key, response.data.auth.user_session_key, sizeof(response.data.auth.user_session_key)); } if (flags & WBFLAG_PAM_UNIX_NAME) { *unix_name = SMB_STRDUP((char *)response.extra_data.data); if (!*unix_name) { free_response(&response); return NT_STATUS_NO_MEMORY; } } free_response(&response); return nt_status; }
void process_complete_pdu(struct pipes_struct *p, struct ncacn_packet *pkt) { bool reply = false; /* Store the call_id */ p->call_id = pkt->call_id; DEBUG(10, ("Processing packet type %u\n", (unsigned int)pkt->ptype)); if (!pipe_init_outgoing_data(p)) { goto done; } switch (pkt->ptype) { case DCERPC_PKT_REQUEST: reply = process_request_pdu(p, pkt); break; case DCERPC_PKT_PING: /* CL request - ignore... */ DEBUG(0, ("Error - Connectionless packet type %u received\n", (unsigned int)pkt->ptype)); break; case DCERPC_PKT_RESPONSE: /* No responses here. */ DEBUG(0, ("Error - DCERPC_PKT_RESPONSE received from client")); break; case DCERPC_PKT_FAULT: case DCERPC_PKT_WORKING: /* CL request - reply to a ping when a call in process. */ case DCERPC_PKT_NOCALL: /* CL - server reply to a ping call. */ case DCERPC_PKT_REJECT: case DCERPC_PKT_ACK: case DCERPC_PKT_CL_CANCEL: case DCERPC_PKT_FACK: case DCERPC_PKT_CANCEL_ACK: DEBUG(0, ("Error - Connectionless packet type %u received\n", (unsigned int)pkt->ptype)); break; case DCERPC_PKT_BIND: /* * We assume that a pipe bind is only in one pdu. */ reply = api_pipe_bind_req(p, pkt); break; case DCERPC_PKT_BIND_ACK: case DCERPC_PKT_BIND_NAK: DEBUG(0, ("Error - DCERPC_PKT_BINDACK/DCERPC_PKT_BINDNACK " "packet type %u received.\n", (unsigned int)pkt->ptype)); break; case DCERPC_PKT_ALTER: /* * We assume that a pipe bind is only in one pdu. */ reply = api_pipe_alter_context(p, pkt); break; case DCERPC_PKT_ALTER_RESP: DEBUG(0, ("Error - DCERPC_PKT_ALTER_RESP received: " "Should only be server -> client.\n")); break; case DCERPC_PKT_AUTH3: /* * The third packet in an auth exchange. */ reply = api_pipe_bind_auth3(p, pkt); break; case DCERPC_PKT_SHUTDOWN: DEBUG(0, ("Error - DCERPC_PKT_SHUTDOWN received: " "Should only be server -> client.\n")); break; case DCERPC_PKT_CO_CANCEL: /* For now just free all client data and continue * processing. */ DEBUG(3,("process_complete_pdu: DCERPC_PKT_CO_CANCEL." " Abandoning rpc call.\n")); /* As we never do asynchronous RPC serving, we can * never cancel a call (as far as I know). * If we ever did we'd have to send a cancel_ack reply. * For now, just free all client data and continue * processing. */ reply = True; break; #if 0 /* Enable this if we're doing async rpc. */ /* We must check the outstanding callid matches. */ if (pipe_init_outgoing_data(p)) { /* Send a cancel_ack PDU reply. */ /* We should probably check the auth-verifier here. */ reply = setup_cancel_ack_reply(p, pkt); } break; #endif case DCERPC_PKT_ORPHANED: /* We should probably check the auth-verifier here. * For now just free all client data and continue * processing. */ DEBUG(3, ("process_complete_pdu: DCERPC_PKT_ORPHANED." " Abandoning rpc call.\n")); reply = True; break; default: DEBUG(0, ("process_complete_pdu: " "Unknown rpc type = %u received.\n", (unsigned int)pkt->ptype)); break; } done: if (!reply) { DEBUG(3,("DCE/RPC fault sent!")); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); } /* pkt and p->in_data.pdu.data freed by caller */ }
static NTSTATUS check_winbind_security(const struct auth_context *auth_context, void *my_private_data, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; wbcErr wbc_status; struct wbcAuthUserParams params; struct wbcAuthUserInfo *info = NULL; struct wbcAuthErrorInfo *err = NULL; ZERO_STRUCT(params); if (!user_info) { return NT_STATUS_INVALID_PARAMETER; } DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name)); if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->mapped.account_name)); return NT_STATUS_INVALID_PARAMETER; } if (strequal(user_info->mapped.domain_name, get_global_sam_name())) { DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n", user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } /* Send off request */ params.account_name = user_info->client.account_name; /* * We need to send the domain name from the client to the DC. With * NTLMv2 the domain name is part of the hashed second challenge, * if we change the domain name, the DC will fail to verify the * challenge cause we changed the domain name, this is like a * man in the middle attack. */ params.domain_name = user_info->client.domain_name; params.workstation_name = user_info->workstation_name; params.flags = 0; params.parameter_control= user_info->logon_parameters; params.level = WBC_AUTH_USER_LEVEL_RESPONSE; memcpy(params.password.response.challenge, auth_context->challenge.data, sizeof(params.password.response.challenge)); if (user_info->password.response.nt.length != 0) { params.password.response.nt_length = user_info->password.response.nt.length; params.password.response.nt_data = user_info->password.response.nt.data; } if (user_info->password.response.lanman.length != 0) { params.password.response.lm_length = user_info->password.response.lanman.length; params.password.response.lm_data = user_info->password.response.lanman.data; } /* we are contacting the privileged pipe */ become_root(); wbc_status = wbcAuthenticateUserEx(¶ms, &info, &err); unbecome_root(); if (!WBC_ERROR_IS_OK(wbc_status)) { DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n", wbcErrorString(wbc_status))); } if (wbc_status == WBC_ERR_NO_MEMORY) { return NT_STATUS_NO_MEMORY; } if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) { struct auth_methods *auth_method = (struct auth_methods *)my_private_data; if ( auth_method ) return auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); return NT_STATUS_LOGON_FAILURE; } if (wbc_status == WBC_ERR_AUTH_ERROR) { nt_status = NT_STATUS(err->nt_status); wbcFreeMemory(err); return nt_status; } if (!WBC_ERROR_IS_OK(wbc_status)) { return NT_STATUS_LOGON_FAILURE; } nt_status = make_server_info_wbcAuthUserInfo(mem_ctx, user_info->client.account_name, user_info->mapped.domain_name, info, server_info); wbcFreeMemory(info); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } (*server_info)->nss_token |= user_info->was_mapped; return nt_status; }
static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, const struct auth_usersupplied_info *user_info, struct auth_user_info_dc **_user_info_dc) { NTSTATUS nt_status; struct auth_user_info_dc *user_info_dc; struct auth_user_info *info; uint32_t error_num; const char *user; user = user_info->client.account_name; if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { nt_status = nt_status_string_to_code(user); } else { error_num = strtoul(user, NULL, 16); DEBUG(5,("name_to_ntstatus_check_password: Error for user %s was 0x%08X\n", user, error_num)); nt_status = NT_STATUS(error_num); } NT_STATUS_NOT_OK_RETURN(nt_status); user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); NT_STATUS_HAVE_NO_MEMORY(user_info_dc); /* This returns a pointer to a struct dom_sid, which is the * same as a 1 element list of struct dom_sid */ user_info_dc->num_sids = 1; user_info_dc->sids = dom_sid_parse_talloc(user_info_dc, SID_NT_ANONYMOUS); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->sids); /* annoying, but the Anonymous really does have a session key, and it is all zeros! */ user_info_dc->user_session_key = data_blob_talloc(user_info_dc, NULL, 16); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->user_session_key.data); user_info_dc->lm_session_key = data_blob_talloc(user_info_dc, NULL, 16); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->lm_session_key.data); data_blob_clear(&user_info_dc->user_session_key); data_blob_clear(&user_info_dc->lm_session_key); user_info_dc->info = info = talloc_zero(user_info_dc, struct auth_user_info); NT_STATUS_HAVE_NO_MEMORY(user_info_dc->info); info->account_name = talloc_asprintf(user_info_dc, "NAME TO NTSTATUS %s ANONYMOUS LOGON", user); NT_STATUS_HAVE_NO_MEMORY(info->account_name); info->domain_name = talloc_strdup(user_info_dc, "NT AUTHORITY"); NT_STATUS_HAVE_NO_MEMORY(info->domain_name); info->full_name = talloc_asprintf(user_info_dc, "NAME TO NTSTATUS %s Anonymous Logon", user); NT_STATUS_HAVE_NO_MEMORY(info->full_name); info->logon_script = talloc_strdup(user_info_dc, ""); NT_STATUS_HAVE_NO_MEMORY(info->logon_script); info->profile_path = talloc_strdup(user_info_dc, ""); NT_STATUS_HAVE_NO_MEMORY(info->profile_path); info->home_directory = talloc_strdup(user_info_dc, ""); NT_STATUS_HAVE_NO_MEMORY(info->home_directory); info->home_drive = talloc_strdup(user_info_dc, ""); NT_STATUS_HAVE_NO_MEMORY(info->home_drive); info->last_logon = 0; info->last_logoff = 0; info->acct_expiry = 0; info->last_password_change = 0; info->allow_password_change = 0; info->force_password_change = 0; info->logon_count = 0; info->bad_password_count = 0; info->acct_flags = ACB_NORMAL; info->authenticated = true; *_user_info_dc = user_info_dc; return nt_status; }
BOOL create_next_pdu(pipes_struct *p) { RPC_HDR_RESP hdr_resp; BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); BOOL auth_seal = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0); uint32 ss_padding_len = 0; uint32 data_len; uint32 data_space_available; uint32 data_len_left; prs_struct outgoing_pdu; uint32 data_pos; /* * If we're in the fault state, keep returning fault PDU's until * the pipe gets closed. JRA. */ if(p->fault_state) { setup_fault_pdu(p, NT_STATUS(0x1c010002)); return True; } memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); /* Change the incoming request header to a response. */ p->hdr.pkt_type = RPC_RESPONSE; /* Set up rpc header flags. */ if (p->out_data.data_sent_length == 0) { p->hdr.flags = RPC_FLG_FIRST; } else { p->hdr.flags = 0; } /* * Work out how much we can fit in a single PDU. */ data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; if(p->ntlmssp_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN); } else if(p->netsec_auth_validated) { data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN); } /* * The amount we send is the minimum of the available * space and the amount left to send. */ data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* * Ensure there really is data left to send. */ if(!data_len_left) { DEBUG(0,("create_next_pdu: no data left to send !\n")); return False; } data_len = MIN(data_len_left, data_space_available); /* * Set up the alloc hint. This should be the data left to * send. */ hdr_resp.alloc_hint = data_len_left; /* * Work out if this PDU will be the last. */ if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; if ((auth_seal || auth_verify) && (data_len_left % 8)) { ss_padding_len = 8 - (data_len_left % 8); DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n", ss_padding_len )); } } /* * Set up the header lengths. */ if (p->ntlmssp_auth_validated) { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; } else if (p->netsec_auth_validated) { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; } else { p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; p->hdr.auth_len = 0; } /* * Init the parse struct to point at the outgoing * data. */ prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } /* Store the current offset. */ data_pos = prs_offset(&outgoing_pdu); /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* Copy the sign/seal padding data. */ if (ss_padding_len) { char pad[8]; memset(pad, '\0', 8); if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); prs_mem_free(&outgoing_pdu); return False; } } if (p->ntlmssp_auth_validated) { /* * NTLMSSP processing. Mutually exclusive with Schannel. */ uint32 crc32 = 0; char *data; DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n", BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len)); /* * Set data to point to where we copied the data into. */ data = prs_data_p(&outgoing_pdu) + data_pos; if (auth_seal) { crc32 = crc32_calc_buffer(data, data_len + ss_padding_len); NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len); } if (auth_seal || auth_verify) { RPC_HDR_AUTH auth_info; init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL, (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0)); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } } if (auth_verify) { RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; char *auth_data = prs_data_p(&outgoing_pdu); p->ntlmssp_seq_num++; init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION, crc32, p->ntlmssp_seq_num++); auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4; if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n")); prs_mem_free(&outgoing_pdu); return False; } NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); } } else if (p->netsec_auth_validated) { /* * Schannel processing. Mutually exclusive with NTLMSSP. */ int auth_type, auth_level; char *data; RPC_HDR_AUTH auth_info; RPC_AUTH_NETSEC_CHK verf; prs_struct rverf; prs_struct rauth; data = prs_data_p(&outgoing_pdu) + data_pos; /* Check it's the type of reply we were expecting to decode */ get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level); init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); prs_mem_free(&outgoing_pdu); return False; } prs_init(&rverf, 0, p->mem_ctx, MARSHALL); prs_init(&rauth, 0, p->mem_ctx, MARSHALL); netsec_encode(&p->netsec_auth, p->netsec_auth.auth_flags, SENDER_IS_ACCEPTOR, &verf, data, data_len + ss_padding_len); smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, &verf, &outgoing_pdu, 0); p->netsec_auth.seq_num++; } /* * Setup the counts for this PDU. */ p->out_data.data_sent_length += data_len; p->out_data.current_pdu_len = p->hdr.frag_len; p->out_data.current_pdu_sent = 0; prs_mem_free(&outgoing_pdu); return True; }