Exemple #1
0
BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
                      prs_struct *data, prs_struct *rdata)
{
	uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent;
	NTSTATUS nt_status;
	BOOL ret = False;
	uint32 callid = 0;
	fstring dump_name;

	auth_len = 0;
	real_auth_len = 0;
	auth_hdr_len = 0;

	if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {	
		if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {	
			auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
		}
		if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {	
			auth_len = RPC_AUTH_NETSEC_CHK_LEN;
		}
		auth_hdr_len = RPC_HDR_AUTH_LEN;
	}

	/*
	 * calc how much actual data we can send in a PDU fragment
	 */
	max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
		auth_hdr_len - auth_len - 8;
	
	for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) {
		prs_struct outgoing_packet;
		prs_struct sec_blob;
		uint32 data_len, send_size;
		uint8 flags = 0;
		uint32 auth_padding = 0;
		DATA_BLOB sign_blob;

		/*
		 * how much will we send this time
		 */
		send_size = MIN(data_left, max_data);

		if (!prs_init(&sec_blob, send_size, /* will need at least this much */
			      cli->mem_ctx, MARSHALL)) {
			DEBUG(0,("Could not malloc %u bytes",
				 send_size+auth_padding));
			return False;
		}

		if(!prs_append_some_prs_data(&sec_blob, data, 
					     data_sent, send_size)) {
			DEBUG(0,("Failed to append data to netsec blob\n"));
			prs_mem_free(&sec_blob);
			return False;
		}

		/*
		 * NT expects the data that is sealed to be 8-byte
		 * aligned. The padding must be encrypted as well and
		 * taken into account when generating the
		 * authentication verifier. The amount of padding must
		 * be stored in the auth header.
		 */

		if (cli->pipe_auth_flags) {
			size_t data_and_padding_size;
			int auth_type;
			int auth_level;
			prs_align_uint64(&sec_blob);

			get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);

			data_and_padding_size = prs_offset(&sec_blob);
			auth_padding = data_and_padding_size - send_size;

			/* insert the auth header */
			
			if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) {
				prs_mem_free(&sec_blob);
				return False;
			}
			
			/* create an NTLMSSP signature */
			if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
				/*
				 * Seal the outgoing data if requested.
				 */
				if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
					
					nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state,
									       (unsigned char*)prs_data_p(&sec_blob),
									       data_and_padding_size,
									       &sign_blob);
					if (!NT_STATUS_IS_OK(nt_status)) {
						prs_mem_free(&sec_blob);
						return False;
					}
				} 
				else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
					
					nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state,
									       (unsigned char*)prs_data_p(&sec_blob),
									       data_and_padding_size, &sign_blob);
					if (!NT_STATUS_IS_OK(nt_status)) {
						prs_mem_free(&sec_blob);
						return False;
					}
				}
				

				/* write auth footer onto the packet */
				real_auth_len = sign_blob.length;
				
				prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length);
				data_blob_free(&sign_blob);

			}
			else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {	
				size_t parse_offset_marker;
				RPC_AUTH_NETSEC_CHK verf;
				DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num));
				
				netsec_encode(&cli->auth_info, 
					      cli->pipe_auth_flags,
					      SENDER_IS_INITIATOR,
					      &verf,
					      prs_data_p(&sec_blob),
					      data_and_padding_size);

				cli->auth_info.seq_num++;

				/* write auth footer onto the packet */
				
				parse_offset_marker = prs_offset(&sec_blob);
				if (!smb_io_rpc_auth_netsec_chk("", &verf,
								&sec_blob, 0)) {
					prs_mem_free(&sec_blob);
					return False;
				}
				real_auth_len = prs_offset(&sec_blob) - parse_offset_marker;
			}
		}

		data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob);

		/*
		 * Malloc parse struct to hold it (and enough for alignments).
		 */
		if(!prs_init(&outgoing_packet, data_len + 8, 
			     cli->mem_ctx, MARSHALL)) {
			DEBUG(0,("rpc_api_pipe_req: Failed to malloc %u bytes.\n", (unsigned int)data_len ));
			return False;
		}

		if (data_left == prs_offset(data))
			flags |= RPC_FLG_FIRST;

		if (data_left <= max_data)
			flags |= RPC_FLG_LAST;
		/*
		 * Write out the RPC header and the request header.
		 */
		if(!(callid = create_rpc_request(&outgoing_packet, op_num, 
						 data_len, real_auth_len, flags, 
						 callid, data_left))) {
			DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n"));
			prs_mem_free(&outgoing_packet);
			prs_mem_free(&sec_blob);
			return False;
		}

		prs_append_prs_data(&outgoing_packet, &sec_blob);
		prs_mem_free(&sec_blob);

		DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, 
			   prs_offset(&outgoing_packet)));
		
		if (flags & RPC_FLG_LAST)
			ret = rpc_api_pipe(cli, &outgoing_packet, 
					   rdata, RPC_RESPONSE);
		else {
			cli_write(cli, cli->nt_pipe_fnum, 0x0008,
				   prs_data_p(&outgoing_packet),
				   data_sent, data_len);
		}
		prs_mem_free(&outgoing_packet);
		data_sent += send_size;
		data_left -= send_size;
	}
	/* Also capture received data */
	slprintf(dump_name, sizeof(dump_name) - 1, "reply_%s",
		 cli_pipe_get_name(cli));
	prs_dump(dump_name, op_num, rdata);

	return ret;
}
Exemple #2
0
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, &current_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, &current_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;
}
Exemple #3
0
static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, 
				    uint32 rpc_call_id,
				    RPC_IFACE *abstract, RPC_IFACE *transfer,
				    const char *my_name, const char *domain)
{
	RPC_HDR hdr;
	RPC_HDR_RB hdr_rb;
	RPC_HDR_AUTH hdr_auth;
	int auth_len = 0;
	int auth_type, auth_level;
	size_t saved_hdr_offset = 0;

	prs_struct auth_info;
	prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */
		prs_get_mem_context(rpc_out), MARSHALL);

	if (cli->pipe_auth_flags) {
		get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
		
		/*
		 * Create the auth structs we will marshall.
		 */
		
		init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0x00, 1);
		
		/*
		 * Now marshall the data into the temporary parse_struct.
		 */
		
		if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) {
			DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_AUTH.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}
		saved_hdr_offset = prs_offset(&auth_info);
	}
	
	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {

		NTSTATUS nt_status;
		DATA_BLOB null_blob = data_blob(NULL, 0);
		DATA_BLOB request;

		DEBUG(5, ("Processing NTLMSSP Negotiate\n"));
		nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
					   null_blob,
					   &request);

		if (!NT_STATUS_EQUAL(nt_status, 
				     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			prs_mem_free(&auth_info);
			return nt_status;
		}

		/* Auth len in the rpc header doesn't include auth_header. */
		auth_len = request.length;
		prs_copy_data_in(&auth_info, (char *)request.data, request.length);

		DEBUG(5, ("NTLMSSP Negotiate:\n"));
		dump_data(5, (const char *)request.data, request.length);

		data_blob_free(&request);

	} else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		RPC_AUTH_NETSEC_NEG netsec_neg;

		/* Use lp_workgroup() if domain not specified */

		if (!domain || !domain[0]) {
			DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n"));
			domain = lp_workgroup();
		}

		init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name);

		/*
		 * Now marshall the data into the temporary parse_struct.
		 */

		if(!smb_io_rpc_auth_netsec_neg("netsec_neg",
					       &netsec_neg, &auth_info, 0)) {
			DEBUG(0,("Failed to marshall RPC_AUTH_NETSEC_NEG.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}

		/* Auth len in the rpc header doesn't include auth_header. */
		auth_len = prs_offset(&auth_info) - saved_hdr_offset;
	}

	/* Create the request RPC_HDR */
	init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, 
		RPC_HEADER_LEN + RPC_HDR_RB_LEN + prs_offset(&auth_info),
		auth_len);

	if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR.\n"));
		prs_mem_free(&auth_info);
		return NT_STATUS_NO_MEMORY;
	}

	/* create the bind request RPC_HDR_RB */
	init_rpc_hdr_rb(&hdr_rb, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, 0x0,
			0x1, 0x0, 0x1, abstract, transfer);

	/* Marshall the bind request data */
	if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_RB.\n"));
		prs_mem_free(&auth_info);
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * Grow the outgoing buffer to store any auth info.
	 */

	if(auth_len != 0) {
		if(!prs_append_prs_data( rpc_out, &auth_info)) {
			DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}
	}
	prs_mem_free(&auth_info);
	return NT_STATUS_OK;
}
Exemple #4
0
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",
			p->name ));
		set_incoming_fault(p);
		setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR));
		return;
	}

	prs_init( &rpc_in, 0, 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, p->name));
			break;

		case RPC_RESPONSE: /* No responses here. */
			DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n",
				p->name ));
			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, p->name));
			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, p->name));
			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",
				p->name));
			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",
				p->name));
			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", p->pipe_srv_name));
		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.
		 */
		p->in_data.pdu_needed_len = 0;
		p->in_data.pdu_received_len = 0;
	}

	prs_mem_free(&rpc_in);
}
Exemple #5
0
static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name)
{
	RPC_IFACE abstract;
	RPC_IFACE transfer;
	prs_struct rpc_out;
	prs_struct rdata;
	uint32 rpc_call_id;
	char buffer[MAX_PDU_FRAG_LEN];

	if ( (pipe_idx < 0) || (pipe_idx >= PI_MAX_PIPES) )
		return False;

	DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->nt_pipe_fnum, pipe_names[pipe_idx].client_pipe));

	if (!valid_pipe_name(pipe_idx, &abstract, &transfer))
		return False;

	prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL);

	/*
	 * Use the MAX_PDU_FRAG_LEN buffer to store the bind request.
	 */

	prs_give_memory( &rpc_out, buffer, sizeof(buffer), False);

	rpc_call_id = get_rpc_call_id();

	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		fstring password;

		DEBUG(5, ("NTLMSSP authenticated pipe selected\n"));

		nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state);
		
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		/* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */

		cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;

		nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, 
						 cli->user_name);
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, 
					       cli->domain);	
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		if (cli->pwd.null_pwd) {
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 NULL);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		} else {
			pwd_get_cleartext(&cli->pwd, password);
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 password);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
		}
	} else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		cli->auth_info.seq_num = 0;
	}

	/* Marshall the outgoing data. */
	create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
	                    &abstract, &transfer,
	                    global_myname(), cli->domain);

	/* Initialize the incoming data struct. */
	prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);

	/* send data on \PIPE\.  receive a response */
	if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) {
		RPC_HDR_BA   hdr_ba;

		DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n"));

		if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) {
			DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		if(!check_bind_response(&hdr_ba, pipe_idx, &transfer)) {
			DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		cli->max_xmit_frag = hdr_ba.bba.max_tsize;
		cli->max_recv_frag = hdr_ba.bba.max_rsize;

		/*
		 * If we're doing NTLMSSP auth we need to send a reply to
		 * the bind-ack to complete the 3-way challenge response
		 * handshake.
		 */

		if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) 
		    && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) {
			DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}
		prs_mem_free(&rdata);
		return True;
	}

	return False;
}
Exemple #6
0
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 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);

	if(p->netsec_auth_validated)
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_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;

	/*
	 * Set up the header lengths.
	 */

	if (p->ntlmssp_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_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 +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NETSEC_CHK_LEN;
	} else {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
		p->hdr.auth_len = 0;
	}

	/*
	 * 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;

	/*
	 * 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;
	}

	if (p->ntlmssp_auth_validated) {
		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, 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);
			NTLMSSPcalc_p(p, (uchar*)data, data_len);
		}

		if (auth_seal || auth_verify) {
			RPC_HDR_AUTH auth_info;

			init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, auth_info.auth_level,
					(auth_verify ? RPC_HDR_AUTH_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);
		}
	}

	if (p->netsec_auth_validated) {
		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, 
				  RPC_HDR_AUTH_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);

		smb_io_rpc_auth_netsec_chk("", &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;
}
Exemple #7
0
static ssize_t unmarshall_rpc_header(pipes_struct *p)
{
	/*
	 * Unmarshall the header to determine the needed length.
	 */

	prs_struct rpc_in;

	if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
		DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
		set_incoming_fault(p);
		return -1;
	}

	prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);
	prs_set_endian_data( &rpc_in, p->endian);

	prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
					p->in_data.pdu_received_len, False);

	/*
	 * Unmarshall the header as this will tell us how much
	 * data we need to read to get the complete pdu.
	 * This also sets the endian flag in rpc_in.
	 */

	if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
		DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
		set_incoming_fault(p);
		prs_mem_free(&rpc_in);
		return -1;
	}

	/*
	 * Validate the RPC header.
	 */

	if(p->hdr.major != 5 && p->hdr.minor != 0) {
		DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
		set_incoming_fault(p);
		prs_mem_free(&rpc_in);
		return -1;
	}

	/*
	 * If there's not data in the incoming buffer this should be the start of a new RPC.
	 */

	if(prs_offset(&p->in_data.data) == 0) {

		/*
		 * AS/U doesn't set FIRST flag in a BIND packet it seems.
		 */

		if ((p->hdr.pkt_type == RPC_REQUEST) && !(p->hdr.flags & RPC_FLG_FIRST)) {
			/*
			 * Ensure that the FIRST flag is set. If not then we have
			 * a stream missmatch.
			 */

			DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
			set_incoming_fault(p);
			prs_mem_free(&rpc_in);
			return -1;
		}

		/*
		 * If this is the first PDU then set the endianness
		 * flag in the pipe. We will need this when parsing all
		 * data in this RPC.
		 */

		p->endian = rpc_in.bigendian_data;

		DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
				p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));

	} else {

		/*
		 * If this is *NOT* the first PDU then check the endianness
		 * flag in the pipe is the same as that in the PDU.
		 */

		if (p->endian != rpc_in.bigendian_data) {
			DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
			set_incoming_fault(p);
			prs_mem_free(&rpc_in);
			return -1;
		}
	}

	/*
	 * Ensure that the pdu length is sane.
	 */

	if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
		DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
		set_incoming_fault(p);
		prs_mem_free(&rpc_in);
		return -1;
	}

	DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
			(unsigned int)p->hdr.flags ));

	p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;

	prs_mem_free(&rpc_in);

	return 0; /* No extra data processed. */
}
Exemple #8
0
WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
				uint32 file_level, const char *user_name,
				SRV_FILE_INFO_CTR *ctr,	int preferred_len,
				ENUM_HND *hnd)
{
	prs_struct qbuf, rbuf;
	SRV_Q_NET_FILE_ENUM q;
	SRV_R_NET_FILE_ENUM r;
	WERROR result = W_ERROR(ERRgeneral);
	int i;

	ZERO_STRUCT(q);
	ZERO_STRUCT(r);

	/* Initialise parse structures */

	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);

	/* Initialise input parameters */

	init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name, 
				 file_level, ctr, preferred_len, hnd);

	/* Marshall data and send request */

	if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
	    !rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
		goto done;

	/* Unmarshall response */

	if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
		goto done;

	result = r.status;

	if (!W_ERROR_IS_OK(result))
		goto done;

	/* copy the data over to the ctr */

	ZERO_STRUCTP(ctr);

	ctr->switch_value = file_level;

	ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
	
	switch(file_level) {
	case 3:
		ctr->file.info3 = (SRV_FILE_INFO_3 *)talloc(
			mem_ctx, sizeof(SRV_FILE_INFO_3) * ctr->num_entries);

		memset(ctr->file.info3, 0, 
		       sizeof(SRV_FILE_INFO_3) * ctr->num_entries);

		for (i = 0; i < r.ctr.num_entries; i++) {
			SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
			char *s;
			
			/* Copy pointer crap */

			memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3, 
			       sizeof(FILE_INFO_3));

			/* Duplicate strings */

			s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
			if (s)
				init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE);
		
			s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
			if (s)
				init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE);

		}		

		break;
	}

 done:
	prs_mem_free(&qbuf);
	prs_mem_free(&rbuf);

	return result;
}
Exemple #9
0
WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
				 uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
				 int preferred_len, ENUM_HND *hnd)
{
	prs_struct qbuf, rbuf;
	SRV_Q_NET_SHARE_ENUM q;
	SRV_R_NET_SHARE_ENUM r;
	WERROR result = W_ERROR(ERRgeneral);
	int i;

	ZERO_STRUCT(q);
	ZERO_STRUCT(r);

	/* Initialise parse structures */

	prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
	prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);

	/* Initialise input parameters */

	init_srv_q_net_share_enum(
		&q, cli->srv_name_slash, info_level, preferred_len, hnd);

	/* Marshall data and send request */

	if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
	    !rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
		goto done;

	/* Unmarshall response */

	if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
		goto done;

	result = r.status;

	if (!W_ERROR_IS_OK(result))
		goto done;

	/* Oh yuck yuck yuck - we have to copy all the info out of the
	   SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
	   prs_mem_free() it will all be invalidated.  The various share
	   info structures suck badly too.  This really is gross. */

	ZERO_STRUCTP(ctr);

	if (!r.ctr.num_entries)
		goto done;

	ctr->info_level = info_level;
	ctr->num_entries = r.ctr.num_entries;

	switch(info_level) {
	case 1:
		ctr->share.info1 = (SRV_SHARE_INFO_1 *)talloc(
			mem_ctx, sizeof(SRV_SHARE_INFO_1) * ctr->num_entries);
		
		memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));

		for (i = 0; i < ctr->num_entries; i++) {
			SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
			char *s;
			
			/* Copy pointer crap */

			memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1, 
			       sizeof(SH_INFO_1));

			/* Duplicate strings */

			s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
			if (s)
				init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
		
			s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark);
			if (s)
				init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);

		}		

		break;
	case 2:
		ctr->share.info2 = (SRV_SHARE_INFO_2 *)talloc(
			mem_ctx, sizeof(SRV_SHARE_INFO_2) * ctr->num_entries);
		
		memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));

		for (i = 0; i < ctr->num_entries; i++) {
			SRV_SHARE_INFO_2 *info2 = &ctr->share.info2[i];
			char *s;
			
			/* Copy pointer crap */

			memcpy(&info2->info_2, &r.ctr.share.info2[i].info_2, 
			       sizeof(SH_INFO_2));

			/* Duplicate strings */

			s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname);
			if (s)
				init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);

			s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark);
			if (s)
				init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);

			s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path);
			if (s)
				init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);

			s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd);
			if (s)
				init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
		}
		break;
	}
 done:
	prs_mem_free(&qbuf);
	prs_mem_free(&rbuf);

	return result;
}
Exemple #10
0
static ssize_t process_complete_pdu(pipes_struct *p)
{
	prs_struct rpc_in;
	size_t data_len = p->in_data.pdu_received_len;
	char *data_p = (char *)&p->in_data.current_in_pdu[0];
	BOOL reply = False;

	if(p->fault_state) {
		DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
			p->name ));
		set_incoming_fault(p);
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		return (ssize_t)data_len;
	}

	prs_init( &rpc_in, 0, 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_BIND:
		case RPC_ALTCONT:
			/*
			 * 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_BINDRESP:
			/*
			 * We assume that a pipe bind_resp is only in one pdu.
			 */
			if(pipe_init_outgoing_data(p))
				reply = api_pipe_bind_auth_resp(p, &rpc_in);
			break;
		case RPC_REQUEST:
			reply = process_request_pdu(p, &rpc_in);
			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", p->pipe_srv_name));
		set_incoming_fault(p);
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		prs_mem_free(&rpc_in);
	} else {
		/*
		 * Reset the lengths. We're ready for a new pdu.
		 */
		p->in_data.pdu_needed_len = 0;
		p->in_data.pdu_received_len = 0;
	}

	prs_mem_free(&rpc_in);
	return (ssize_t)data_len;
}
Exemple #11
0
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
			TALLOC_CTX *mem_ctx,
			const struct ndr_interface_table *table,
			uint32 opnum, void *r)
{
#ifdef AVM_SMALL
	return NT_STATUS_NO_MEMORY;
#else
	prs_struct q_ps, r_ps;
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	DATA_BLOB blob;
	struct ndr_push *push;
	NTSTATUS status;
	enum ndr_err_code ndr_err;

	SMB_ASSERT(ndr_syntax_id_equal(&table->syntax_id,
				       &cli->abstract_syntax));
	SMB_ASSERT(table->num_calls > opnum);

	call = &table->calls[opnum];

	push = ndr_push_init_ctx(mem_ctx);
	if (!push) {
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = call->ndr_push(push, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	blob = ndr_push_blob(push);

	if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
		return NT_STATUS_NO_MEMORY;
	}

	talloc_free(push);

	prs_init_empty( &r_ps, mem_ctx, UNMARSHALL );
	
	status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); 

	prs_mem_free( &q_ps );

	if (!NT_STATUS_IS_OK(status)) {
		prs_mem_free( &r_ps );
		return status;
	}

	if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
		prs_mem_free( &r_ps );
		return NT_STATUS_NO_MEMORY;
	}

	prs_mem_free( &r_ps );

	pull = ndr_pull_init_blob(&blob, mem_ctx);
	if (pull == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	/* have the ndr parser alloc memory for us */
	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	ndr_err = call->ndr_pull(pull, NDR_OUT, r);
	talloc_free(pull);

	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	return NT_STATUS_OK;
#endif
}
Exemple #12
0
int psec_getsec(char *printer)
{
	SEC_DESC_BUF *secdesc_ctr = NULL;
	TALLOC_CTX *mem_ctx = NULL;
	fstring keystr, sidstr, tdb_path;
	prs_struct ps;
	int result = 0, i;

	ZERO_STRUCT(ps);

	/* Open tdb for reading */

	slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
		 lp_lockdir());

	tdb = tdb_open(tdb_path, 0, 0, O_RDONLY, 0600);

	if (!tdb) {
		printf("psec: failed to open nt drivers database: %s\n",
		       sys_errlist[errno]);
		return 1;
	}

	/* Get security blob from tdb */

	slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);

	mem_ctx = talloc_init();

	if (!mem_ctx) {
		printf("memory allocation error\n");
		result = 1;
		goto done;
	}

	if (tdb_prs_fetch(tdb, keystr, &ps, mem_ctx) != 0) {
		printf("error fetching descriptor for printer %s\n",
		       printer);
		/* cannot do a prs_mem_free() when tdb_prs_fetch fails */
		/* as the prs structure has not been initialized */
		tdb_close(tdb);
		talloc_destroy(mem_ctx);
		return 1;
	}

	/* Unpack into security descriptor buffer */

	if (!sec_io_desc_buf("nt_printing_getsec", &secdesc_ctr, &ps, 1)) {
		printf("error unpacking sec_desc_buf\n");
		result = 1;
		goto done;
	}

	/* Print owner and group sid */

	if (secdesc_ctr->sec->owner_sid) {
		sid_to_string(sidstr, secdesc_ctr->sec->owner_sid);
	} else {
		fstrcpy(sidstr, "");
	}

	printf("%s\n", sidstr);

	if (secdesc_ctr->sec->grp_sid) {
		sid_to_string(sidstr, secdesc_ctr->sec->grp_sid);
	} else {
		fstrcpy(sidstr, "");
	}

	printf("%s\n", sidstr);

	/* Print aces */

	if (!secdesc_ctr->sec->dacl) {
		result = 0;
		goto done;
	}

	for (i = 0; i < secdesc_ctr->sec->dacl->num_aces; i++) {
		SEC_ACE *ace = &secdesc_ctr->sec->dacl->ace[i];

		sid_to_string(sidstr, &ace->sid);

		printf("%d %d 0x%08x %s\n", ace->type, ace->flags,
		       ace->info.mask, sidstr);
	}

 done:
	if (tdb) tdb_close(tdb);
	if (mem_ctx) talloc_destroy(mem_ctx);
	if (secdesc_ctr) free_sec_desc_buf(&secdesc_ctr);
	prs_mem_free(&ps);

	return result;
}
Exemple #13
0
int psec_setsec(char *printer)
{
	DOM_SID user_sid, group_sid;
	SEC_ACE *ace_list = NULL;
	SEC_ACL *dacl = NULL;
	SEC_DESC *sd;
	SEC_DESC_BUF *sdb = NULL;
	int result = 0, num_aces = 0;
	fstring line, keystr, tdb_path;
	size_t size;
	prs_struct ps;
	TALLOC_CTX *mem_ctx = NULL;
	BOOL has_user_sid = False, has_group_sid = False;

	ZERO_STRUCT(ps);

	/* Open tdb for reading */

	slprintf(tdb_path, sizeof(tdb_path) - 1, "%s/ntdrivers.tdb", 
		 lp_lockdir());

	tdb = tdb_open(tdb_path, 0, 0, O_RDWR, 0600);

	if (!tdb) {
		printf("psec: failed to open nt drivers database: %s\n",
		       sys_errlist[errno]);
		result = 1;
		goto done;
	}

	/* Read owner and group sid */

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&user_sid, line);
		has_user_sid = True;
	}

	fgets(line, sizeof(fstring), stdin);
	if (line[0] != '\n') {
		string_to_sid(&group_sid, line);
		has_group_sid = True;
	}

	/* Read ACEs from standard input for discretionary ACL */

	while(fgets(line, sizeof(fstring), stdin)) {
		int ace_type, ace_flags;
		uint32 ace_mask;
		fstring sidstr;
		DOM_SID sid;
		SEC_ACCESS sa;

		if (sscanf(line, "%d %d 0x%x %s", &ace_type, &ace_flags, 
			   &ace_mask, sidstr) != 4) {
			continue;
		}

		string_to_sid(&sid, sidstr);
		
		ace_list = Realloc(ace_list, sizeof(SEC_ACE) * 
				   (num_aces + 1));
		
		init_sec_access(&sa, ace_mask);
		init_sec_ace(&ace_list[num_aces], &sid, ace_type, sa, 
			     ace_flags);

		num_aces++;
	}

	dacl = make_sec_acl(ACL_REVISION, num_aces, ace_list);
	free(ace_list);

	/* Create security descriptor */

	sd = make_sec_desc(SEC_DESC_REVISION,
			   has_user_sid ? &user_sid : NULL, 
			   has_group_sid ? &group_sid : NULL,
			   NULL, /* System ACL */
			   dacl, /* Discretionary ACL */
			   &size);

	free_sec_acl(&dacl);

	sdb = make_sec_desc_buf(size, sd);

	free_sec_desc(&sd);

	/* Write security descriptor to tdb */

	mem_ctx = talloc_init();

	if (!mem_ctx) {
		printf("memory allocation error\n");
		result = 1;
		goto done;
	}

	prs_init(&ps, (uint32)sec_desc_size(sdb->sec) + 
		 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);

	if (!sec_io_desc_buf("nt_printing_setsec", &sdb, &ps, 1)) {
		printf("sec_io_desc_buf failed\n");
		goto done;
	}

	slprintf(keystr, sizeof(keystr) - 1, "SECDESC/%s", printer);

	if (!tdb_prs_store(tdb, keystr, &ps)==0) {
		printf("Failed to store secdesc for %s\n", printer);
		goto done;
	}

 done:
	if (tdb) tdb_close(tdb);
	if (sdb) free_sec_desc_buf(&sdb);
	if (mem_ctx) talloc_destroy(mem_ctx);
	prs_mem_free(&ps);

	return result;
}
Exemple #14
0
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        int p_idx, int opnum, void *data,
                        ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn)
{
    prs_struct q_ps, r_ps;
    struct ndr_pull *pull;
    DATA_BLOB blob;
    struct ndr_push *push;
    NTSTATUS status;

    SMB_ASSERT(cli->pipe_idx == p_idx);

    push = ndr_push_init_ctx(mem_ctx);
    if (!push) {
        return NT_STATUS_NO_MEMORY;
    }

    status = push_fn(push, NDR_IN, data);
    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    blob = ndr_push_blob(push);

    if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
        return NT_STATUS_NO_MEMORY;
    }

    talloc_free(push);

    if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) {
        prs_mem_free( &q_ps );
        return NT_STATUS_NO_MEMORY;
    }

    status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps);

    prs_mem_free( &q_ps );

    if (!NT_STATUS_IS_OK(status)) {
        prs_mem_free( &r_ps );
        return status;
    }

    if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
        prs_mem_free( &r_ps );
        return NT_STATUS_NO_MEMORY;
    }

    prs_mem_free( &r_ps );

    pull = ndr_pull_init_blob(&blob, mem_ctx);
    if (pull == NULL) {
        return NT_STATUS_NO_MEMORY;
    }

    /* have the ndr parser alloc memory for us */
    pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    status = pull_fn(pull, NDR_OUT, data);
    talloc_free(pull);

    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    return NT_STATUS_OK;
}