static int rpc_recv(struct rpc *rpc) { struct rpc_request_hdr_t hdr; struct rpc_reply_t reply; LOG_ENTRY; memset(&reply, 0, sizeof(reply)); if (rpc_read(rpc->fd, &hdr, sizeof(hdr)) < 0) { RPC_PERROR("rpc_read"); goto fail; } RPC_DEBUG("<<< header code %x", hdr.code); if (rpc->handler(&hdr, &reply)) { RPC_ERROR("failed to handle message"); goto fail; } RPC_DEBUG("<<< handled message %x", hdr.code); if (rpc_write(rpc->fd, &reply, sizeof(reply)) < 0) { RPC_PERROR("rpc_write"); goto fail; } RPC_DEBUG("<<< done with message %x", hdr.code); LOG_EXIT; return 0; fail: return -1; }
void rdBodyToFile(rdWin *w, char *filename) { FILE *fp; char *buf; assert(w); assert(filename); buf = salloc(w->bodylen+1); if (rpc_settag(wilyq, w->id, "Sending... ")) { DPRINT("Could not change tag"); return; } if (rpc_read(wilyq, w->id, 0, w->bodylen, buf)) { DPRINT("Could not retrieve body text"); return; } if ((fp = fopen(filename, "w"))) { (void)fprintf(fp,"%s",buf); fclose(fp); } else { DPRINT("Could not write body text to a file"); } free(buf); return; }
static int rpc_send(struct rpc *rpc) { LOG_ENTRY; struct rpc_request_t req; pthread_mutex_lock(&rpc->pipe_mtx); int rc = read(rpc->pipefd[READ_END], &req, sizeof(req)); pthread_mutex_unlock(&rpc->pipe_mtx); if (rc < 0) { RPC_PERROR("read"); goto fail; } RPC_DEBUG(">>> code %x", req.header.code); if (rpc_write(rpc->fd, &req.header, sizeof(rpc_request_hdr_t)) < 0) { RPC_PERROR("rpc_write"); goto fail; } RPC_DEBUG(">>> sent header"); if (rpc_read(rpc->fd, &req.reply, sizeof(rpc_reply_t)) < 0) { RPC_PERROR("rpc_read"); goto fail; } RPC_DEBUG(">>> reply code %x", req.reply.code); if (req.reply_marker) { req.reply_marker[0] = 1; } rpc_cond_signal(rpc); LOG_EXIT; return 0; fail: return -1; }
static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rdata, uint8 expected_pkt_type) { uint32 len; char *rparam = NULL; uint32 rparam_len = 0; uint16 setup[2]; BOOL first = True; BOOL last = True; RPC_HDR rhdr; char *pdata = data ? prs_data_p(data) : NULL; uint32 data_len = data ? prs_offset(data) : 0; char *prdata = NULL; uint32 rdata_len = 0; uint32 current_offset = 0; uint32 fragment_start = 0; uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : 1024; int auth_padding_len = 0; /* Create setup parameters - must be in native byte order. */ setup[0] = TRANSACT_DCERPCCMD; setup[1] = cli->nt_pipe_fnum; /* Pipe file handle. */ DEBUG(5,("rpc_api_pipe: fnum:%x\n", (int)cli->nt_pipe_fnum)); /* Send the RPC request and receive a response. For short RPC calls (about 1024 bytes or so) the RPC request and response appears in a SMBtrans request and response. Larger RPC responses are received further on. */ if (!cli_api_pipe(cli, "\\PIPE\\", setup, 2, 0, /* Setup, length, max */ NULL, 0, 0, /* Params, length, max */ pdata, data_len, max_data, /* data, length, max */ &rparam, &rparam_len, /* return params, len */ &prdata, &rdata_len)) /* return data, len */ { DEBUG(0, ("cli_pipe: return critical error. Error was %s\n", cli_errstr(cli))); return False; } /* Throw away returned params - we know we won't use them. */ SAFE_FREE(rparam); if (prdata == NULL) { DEBUG(0,("rpc_api_pipe: pipe %x failed to return data.\n", (int)cli->nt_pipe_fnum)); return False; } /* * Give this memory as dynamically allocated to the return parse * struct. */ prs_give_memory(rdata, prdata, rdata_len, True); current_offset = rdata_len; /* This next call sets the endian bit correctly in rdata. */ if (!rpc_check_hdr(rdata, &rhdr, &first, &last, &len)) { prs_mem_free(rdata); return False; } if (rhdr.pkt_type == RPC_BINDACK) { if (!last && !first) { DEBUG(5,("rpc_api_pipe: bug in server (AS/U?), setting fragment first/last ON.\n")); first = True; last = True; } } if (rhdr.pkt_type == RPC_BINDNACK) { DEBUG(3, ("Bind NACK received on pipe %x!\n", (int)cli->nt_pipe_fnum)); prs_mem_free(rdata); return False; } if (rhdr.pkt_type == RPC_RESPONSE) { RPC_HDR_RESP rhdr_resp; if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0)) { DEBUG(5,("rpc_api_pipe: failed to unmarshal RPC_HDR_RESP.\n")); prs_mem_free(rdata); return False; } } if (rhdr.pkt_type != expected_pkt_type) { DEBUG(3, ("Connection to pipe %x got an unexpected RPC packet type - %d, not %d\n", (int)cli->nt_pipe_fnum, rhdr.pkt_type, expected_pkt_type)); prs_mem_free(rdata); return False; } DEBUG(5,("rpc_api_pipe: len left: %u smbtrans read: %u\n", (unsigned int)len, (unsigned int)rdata_len )); /* check if data to be sent back was too large for one SMBtrans */ /* err status is only informational: the _real_ check is on the length */ if (len > 0) { /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */ /* Read the remaining part of the first response fragment */ if (!rpc_read(cli, rdata, len, ¤t_offset)) { prs_mem_free(rdata); return False; } } /* * Now we have a complete PDU, check the auth struct if any was sent. */ if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { prs_mem_free(rdata); return False; } if (rhdr.auth_len != 0) { /* * Drop the auth footers from the current offset. * We need this if there are more fragments. * The auth footers consist of the auth_data and the * preceeding 8 byte auth_header. */ current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); } /* * Only one rpc fragment, and it has been read. */ if (first && last) { DEBUG(6,("rpc_api_pipe: fragment first and last both set\n")); return True; } /* * Read more fragments using SMBreadX until we get one with the * last bit set. */ while (!last) { RPC_HDR_RESP rhdr_resp; int num_read; char hdr_data[RPC_HEADER_LEN+RPC_HDR_RESP_LEN]; prs_struct hps; uint8 eclass; uint32 ecode; /* * First read the header of the next PDU. */ prs_init(&hps, 0, cli->mem_ctx, UNMARSHALL); prs_give_memory(&hps, hdr_data, sizeof(hdr_data), False); num_read = cli_read(cli, cli->nt_pipe_fnum, hdr_data, 0, RPC_HEADER_LEN+RPC_HDR_RESP_LEN); if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); if (eclass != ERRDOS && ecode != ERRmoredata) { DEBUG(0,("rpc_api_pipe: cli_read error : %d/%d\n", eclass, ecode)); return False; } } DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read)); if (num_read != RPC_HEADER_LEN+RPC_HDR_RESP_LEN) { DEBUG(0,("rpc_api_pipe: Error : requested %d bytes, got %d.\n", RPC_HEADER_LEN+RPC_HDR_RESP_LEN, num_read )); return False; } /* This call sets the endianness in hps. */ if (!rpc_check_hdr(&hps, &rhdr, &first, &last, &len)) return False; /* Ensure the endianness in rdata is set correctly - must be same as hps. */ if (hps.bigendian_data != rdata->bigendian_data) { DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n", rdata->bigendian_data ? "big" : "little", hps.bigendian_data ? "big" : "little" )); return False; } if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0)) { DEBUG(0,("rpc_api_pipe: Error in unmarshalling RPC_HDR_RESP.\n")); return False; } if (first) { DEBUG(0,("rpc_api_pipe: secondary PDU rpc header has 'first' set !\n")); return False; } /* * Now read the rest of the PDU. */ if (!rpc_read(cli, rdata, len, ¤t_offset)) { prs_mem_free(rdata); return False; } fragment_start = current_offset - len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; /* * Verify any authentication footer. */ if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { prs_mem_free(rdata); return False; } if (rhdr.auth_len != 0 ) { /* * Drop the auth footers from the current offset. * The auth footers consist of the auth_data and the * preceeding 8 byte auth_header. * We need this if there are more fragments. */ current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); } } return True; }