From 1f7d18a99c6db90b2c5efb740af02ca279b9445d Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 17 Aug 2002 16:05:44 +0000 Subject: Sync 3.0 branch with HEAD (This used to be commit 3823a2ff5a3c6edf325e2ac31bab50175420f0b1) --- source3/rpc_client/cli_netlogon.c | 978 +++++++----- source3/rpc_client/cli_reg.c | 1118 +------------ source3/rpc_client/cli_samr.c | 1761 ++++++++++++++------- source3/rpc_client/cli_spoolss.c | 2620 +++++++++++++++++++++++-------- source3/rpc_client/cli_spoolss_notify.c | 486 ++---- source3/rpc_client/cli_srvsvc.c | 727 +++++---- source3/rpc_client/cli_wkssvc.c | 122 +- 7 files changed, 4424 insertions(+), 3388 deletions(-) (limited to 'source3/rpc_client') diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 90c8a34c21..acc9135542 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -1,34 +1,258 @@ /* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 1998. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - + Unix SMB/CIFS implementation. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Tim Potter 2001 + Copyright (C) Paul Ashton 1997. + Copyright (C) Jeremy Allison 1998. + Copyright (C) Andrew Bartlett 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -extern pstring global_myname; -extern fstring global_myworkgroup; +/* LSA Request Challenge. Sends our challenge to server, then gets + server response. These are used to generate the credentials. */ + +NTSTATUS cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, + DOM_CHAL *srv_chal) +{ + prs_struct qbuf, rbuf; + NET_Q_REQ_CHAL q; + NET_R_REQ_CHAL r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + extern pstring global_myname; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); + prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + + /* create and send a MSRPC command with api NET_REQCHAL */ + + DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n", + global_myname, cli->desthost, credstr(clnt_chal->data))); + + /* store the parameters */ + init_q_req_chal(&q, cli->srv_name_slash, global_myname, clnt_chal); + + /* Marshall data and send request */ + + if (!net_io_q_req_chal("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_REQCHAL, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarhall response */ + + if (!net_io_r_req_chal("", &r, &rbuf, 0)) { + goto done; + } + + result = r.status; + + /* Return result */ + + if (NT_STATUS_IS_OK(result)) { + memcpy(srv_chal, r.srv_chal.data, sizeof(srv_chal->data)); + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/**************************************************************************** +LSA Authenticate 2 + +Send the client credential, receive back a server credential. +Ensure that the server credential returned matches the session key +encrypt of the server challenge originally received. JRA. +****************************************************************************/ + +NTSTATUS cli_net_auth2(struct cli_state *cli, + uint16 sec_chan, + uint32 neg_flags, DOM_CHAL *srv_chal) +{ + prs_struct qbuf, rbuf; + NET_Q_AUTH_2 q; + NET_R_AUTH_2 r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + extern pstring global_myname; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); + prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + + /* create and send a MSRPC command with api NET_AUTH2 */ + + DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n", + cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname, + credstr(cli->clnt_cred.challenge.data), neg_flags)); + + /* store the parameters */ + init_q_auth_2(&q, cli->srv_name_slash, cli->mach_acct, + sec_chan, global_myname, &cli->clnt_cred.challenge, + neg_flags); + + /* turn parameters into data stream */ + + if (!net_io_q_auth_2("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_AUTH2, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!net_io_r_auth_2("", &r, &rbuf, 0)) { + goto done; + } + + result = r.status; + + if (NT_STATUS_IS_OK(result)) { + UTIME zerotime; + + /* + * Check the returned value using the initial + * server received challenge. + */ + + zerotime.time = 0; + if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, + zerotime) == 0) { + + /* + * Server replied with bad credential. Fail. + */ + DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \ +password ?).\n", cli->desthost )); + result = NT_STATUS_ACCESS_DENIED; + goto done; + } + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Initialize domain session credentials */ + +NTSTATUS cli_nt_setup_creds(struct cli_state *cli, + uint16 sec_chan, + const unsigned char mach_pwd[16]) +{ + DOM_CHAL clnt_chal; + DOM_CHAL srv_chal; + UTIME zerotime; + NTSTATUS result; + + /******************* Request Challenge ********************/ + + generate_random_buffer(clnt_chal.data, 8, False); + + /* send a client challenge; receive a server challenge */ + result = cli_net_req_chal(cli, &clnt_chal, &srv_chal); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("cli_nt_setup_creds: request challenge failed\n")); + return result; + } + + /**************** Long-term Session key **************/ + + /* calculate the session key */ + cred_session_key(&clnt_chal, &srv_chal, mach_pwd, + cli->sess_key); + memset((char *)cli->sess_key+8, '\0', 8); + + /******************* Authenticate 2 ********************/ + + /* calculate auth-2 credentials */ + zerotime.time = 0; + cred_create(cli->sess_key, &clnt_chal, zerotime, + &cli->clnt_cred.challenge); + + /* + * Send client auth-2 challenge. + * Receive an auth-2 challenge response and check it. + */ + + result = cli_net_auth2(cli, sec_chan, 0x000001ff, &srv_chal); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1,("cli_nt_setup_creds: auth2 challenge failed %s\n", + nt_errstr(result))); + } + + return result; +} + +/* Logon Control 2 */ + +NTSTATUS cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 query_level) +{ + prs_struct qbuf, rbuf; + NET_Q_LOGON_CTRL2 q; + NET_R_LOGON_CTRL2 r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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_net_q_logon_ctrl2(&q, cli->srv_name_slash, query_level); + + /* Marshall data and send request */ + + if (!net_io_q_logon_ctrl2("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_LOGON_CTRL2, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!net_io_r_logon_ctrl2("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} /**************************************************************************** -Generate the next creds to use. +Generate the next creds to use. Yuck - this is a cut&paste from another +file. They should be combined at some stage. )-: ****************************************************************************/ static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred) @@ -47,424 +271,394 @@ static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred) } -#if UNUSED_CODE -/**************************************************************************** -do a LSA Logon Control2 -****************************************************************************/ -BOOL cli_net_logon_ctrl2(struct cli_state *cli, NTSTATUS status_level) +/* Sam synchronisation */ + +NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_CRED *ret_creds, + uint32 database_id, uint32 *num_deltas, + SAM_DELTA_HDR **hdr_deltas, + SAM_DELTA_CTR **deltas) { - prs_struct rbuf; - prs_struct buf; - NET_Q_LOGON_CTRL2 q_l; - BOOL ok = False; - - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_LOGON_CTRL2 */ - - DEBUG(4,("do_net_logon_ctrl2 from %s status level:%x\n", - global_myname, status_level)); - - /* store the parameters */ - init_q_logon_ctrl2(&q_l, cli->srv_name_slash, - status_level); - - /* turn parameters into data stream */ - if(!net_io_q_logon_ctrl2("", &q_l, &buf, 0)) { - DEBUG(0,("cli_net_logon_ctrl2: Error : failed to marshall NET_Q_LOGON_CTRL2 struct.\n")); - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, NET_LOGON_CTRL2, &buf, &rbuf)) - { - NET_R_LOGON_CTRL2 r_l; - - /* - * Unmarshall the return buffer. - */ - ok = net_io_r_logon_ctrl2("", &r_l, &rbuf, 0); - - if (ok && r_l.status != 0) - { - /* report error code */ - DEBUG(0,("do_net_logon_ctrl2: Error %s\n", nt_errstr(r_l.status))); - cli->nt_error = r_l.status; - ok = False; - } - } - - prs_mem_free(&buf); - prs_mem_free(&rbuf); - - return ok; -} -#endif + prs_struct qbuf, rbuf; + NET_Q_SAM_SYNC q; + NET_R_SAM_SYNC r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds; -/**************************************************************************** -LSA Authenticate 2 + ZERO_STRUCT(q); + ZERO_STRUCT(r); -Send the client credential, receive back a server credential. -Ensure that the server credential returned matches the session key -encrypt of the server challenge originally received. JRA. -****************************************************************************/ + /* Initialise parse structures */ -NTSTATUS cli_net_auth2(struct cli_state *cli, uint16 sec_chan, - uint32 neg_flags, DOM_CHAL *srv_chal) -{ - prs_struct rbuf; - prs_struct buf; - NET_Q_AUTH_2 q_a; - BOOL ok = False; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_AUTH2 */ - - DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n", - cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname, - credstr(cli->clnt_cred.challenge.data), neg_flags)); - - /* store the parameters */ - init_q_auth_2(&q_a, cli->srv_name_slash, cli->mach_acct, - sec_chan, global_myname, &cli->clnt_cred.challenge, neg_flags); - - /* turn parameters into data stream */ - if(!net_io_q_auth_2("", &q_a, &buf, 0)) { - DEBUG(0,("cli_net_auth2: Error : failed to marshall NET_Q_AUTH_2 struct.\n")); - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return result; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, NET_AUTH2, &buf, &rbuf)) - { - NET_R_AUTH_2 r_a; - - ok = net_io_r_auth_2("", &r_a, &rbuf, 0); - result = r_a.status; - - if (ok && !NT_STATUS_IS_OK(result)) - { - /* report error code */ - DEBUG(0,("cli_net_auth2: Error %s\n", nt_errstr(result))); - ok = False; - } - - if (ok) - { - /* - * Check the returned value using the initial - * server received challenge. - */ - UTIME zerotime; - - zerotime.time = 0; - if(cred_assert( &r_a.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - ok = False; - } - } - -#if 0 - /* - * Try commenting this out to see if this makes the connect - * work for a NT 3.51 PDC. JRA. - */ - - if (ok && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags) - { - /* report different neg_flags */ - DEBUG(0,("cli_net_auth2: error neg_flags (q,r) differ - (%x,%x)\n", - q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags)); - ok = False; - } -#endif - - } - - prs_mem_free(&buf); - prs_mem_free(&rbuf); - - return result; -} + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); -/**************************************************************************** -LSA Request Challenge. Sends our challenge to server, then gets -server response. These are used to generate the credentials. -****************************************************************************/ + /* Initialise input parameters */ -BOOL cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal) -{ - prs_struct rbuf; - prs_struct buf; - NET_Q_REQ_CHAL q_c; - BOOL valid_chal = False; - - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_REQCHAL */ - - DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n", - cli->desthost, global_myname, credstr(clnt_chal->data))); - - /* store the parameters */ - init_q_req_chal(&q_c, cli->srv_name_slash, - global_myname, clnt_chal); - - /* turn parameters into data stream */ - if(!net_io_q_req_chal("", &q_c, &buf, 0)) { - DEBUG(0,("cli_net_req_chal: Error : failed to marshall NET_Q_REQ_CHAL struct.\n")); - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, NET_REQCHAL, &buf, &rbuf)) - { - NET_R_REQ_CHAL r_c; - BOOL ok; - - ok = net_io_r_req_chal("", &r_c, &rbuf, 0); - - if (ok && !NT_STATUS_IS_OK(r_c.status)) - { - /* report error code */ - DEBUG(0,("cli_net_req_chal: Error %s\n", nt_errstr(r_c.status))); - ok = False; - } - - if (ok) - { - /* ok, at last: we're happy. return the challenge */ - memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data)); - valid_chal = True; - } - } - - prs_mem_free(&buf); - prs_mem_free(&rbuf); - - return valid_chal; + gen_next_creds(cli, &clnt_creds); + + init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2, + &clnt_creds, ret_creds, database_id); + + /* Marshall data and send request */ + + if (!net_io_q_sam_sync("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAM_SYNC, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!net_io_r_sam_sync("", cli->sess_key, &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Return results */ + + result = r.status; + *num_deltas = r.num_deltas2; + *hdr_deltas = r.hdr_deltas; + *deltas = r.deltas; + + memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/*************************************************************************** - LSA SAM Logon internal - interactive or network. Does level 2 or 3 but always - returns level 3. -****************************************************************************/ -static NTSTATUS cli_net_sam_logon_internal(struct cli_state *cli, NET_ID_INFO_CTR *ctr, - NET_USER_INFO_3 *user_info3, - uint16 validation_level) +/* Sam synchronisation */ + +NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 database_id, UINT64_S seqnum, + uint32 *num_deltas, + SAM_DELTA_HDR **hdr_deltas, + SAM_DELTA_CTR **deltas) { - DOM_CRED new_clnt_cred; - DOM_CRED dummy_rtn_creds; - prs_struct rbuf; - prs_struct buf; - NET_Q_SAM_LOGON q_s; - NET_R_SAM_LOGON r_s; - NTSTATUS retval = NT_STATUS_OK; + prs_struct qbuf, rbuf; + NET_Q_SAM_DELTAS q; + NET_R_SAM_DELTAS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds; - gen_next_creds( cli, &new_clnt_cred); + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + /* Initialise parse structures */ - /* create and send a MSRPC command with api NET_SAMLOGON */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("cli_net_sam_logon_internal: srv:%s mc:%s clnt %s %x ll: %d\n", - cli->srv_name_slash, global_myname, - credstr(new_clnt_cred.challenge.data), cli->clnt_cred.timestamp.time, - ctr->switch_value)); + /* Initialise input parameters */ - memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); - dummy_rtn_creds.timestamp.time = time(NULL); + gen_next_creds(cli, &clnt_creds); - /* store the parameters */ - q_s.validation_level = validation_level; - init_sam_info(&q_s.sam_id, cli->srv_name_slash, - global_myname, &new_clnt_cred, &dummy_rtn_creds, - ctr->switch_value, ctr); + init_net_q_sam_deltas(&q, cli->srv_name_slash, + cli->clnt_name_slash + 2, &clnt_creds, + database_id, seqnum); - /* turn parameters into data stream */ - if(!net_io_q_sam_logon("", &q_s, &buf, 0)) { - DEBUG(0,("cli_net_sam_logon_internal: Error : failed to marshall NET_Q_SAM_LOGON struct.\n")); - retval = NT_STATUS_NO_MEMORY; - goto out; - } + /* Marshall data and send request */ - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, NET_SAMLOGON, &buf, &rbuf)) { - DEBUG(0,("cli_net_sam_logon_internal: Error rpc_api_pipe_req failed.\n")); - retval = NT_STATUS_UNSUCCESSFUL; - goto out; + if (!net_io_q_sam_deltas("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAM_DELTAS, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - r_s.user = user_info3; + /* Unmarshall response */ - if(!net_io_r_sam_logon("", &r_s, &rbuf, 0)) { - DEBUG(0,("cli_net_sam_logon_internal: Error : failed to unmarshal NET_R_SAM_LOGON struct.\n")); - retval = NT_STATUS_NO_MEMORY; - goto out; + if (!net_io_r_sam_deltas("", cli->sess_key, &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - - retval = r_s.status; - /* - * Don't treat NT_STATUS_INVALID_INFO_CLASS as an error - we will re-issue - * the call. - */ - - if (NT_STATUS_V(retval) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) { - goto out; - } + /* Return results */ - if (!NT_STATUS_IS_OK(retval)) { - /* report error code */ - DEBUG(0,("cli_net_sam_logon_internal: %s\n", nt_errstr(r_s.status))); - goto out; - } + result = r.status; + *num_deltas = r.num_deltas2; + *hdr_deltas = r.hdr_deltas; + *deltas = r.deltas; - /* Update the credentials. */ - if (!clnt_deal_with_creds(cli->sess_key, &cli->clnt_cred, &r_s.srv_creds)) { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_sam_logon_internal: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - retval = NT_STATUS_WRONG_PASSWORD; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Logon domain user */ + +NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *username, char *password, + int logon_type) +{ + prs_struct qbuf, rbuf; + NET_Q_SAM_LOGON q; + NET_R_SAM_LOGON r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds, dummy_rtn_creds; + extern pstring global_myname; + NET_ID_INFO_CTR ctr; + NET_USER_INFO_3 user; + int validation_level = 3; + + 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 */ + + gen_next_creds(cli, &clnt_creds); + + q.validation_level = validation_level; + + memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); + dummy_rtn_creds.timestamp.time = time(NULL); + + ctr.switch_value = logon_type; + + switch (logon_type) { + case INTERACTIVE_LOGON_TYPE: { + unsigned char lm_owf_user_pwd[16], nt_owf_user_pwd[16]; + + nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd); + + init_id_info1(&ctr.auth.id1, lp_workgroup(), + 0, /* param_ctrl */ + 0xdead, 0xbeef, /* LUID? */ + username, cli->clnt_name_slash, + cli->sess_key, lm_owf_user_pwd, + nt_owf_user_pwd); + + break; + } + case NET_LOGON_TYPE: { + uint8 chal[8]; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + + generate_random_buffer(chal, 8, False); + + SMBencrypt(password, chal, local_lm_response); + SMBNTencrypt(password, chal, local_nt_response); + + init_id_info2(&ctr.auth.id2, lp_workgroup(), + 0, /* param_ctrl */ + 0xdead, 0xbeef, /* LUID? */ + username, cli->clnt_name_slash, chal, + local_lm_response, 24, local_nt_response, 24); + break; + } + default: + DEBUG(0, ("switch value %d not supported\n", + ctr.switch_value)); + goto done; + } + + init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname, + &clnt_creds, &dummy_rtn_creds, logon_type, + &ctr); + + /* Marshall data and send request */ + + if (!net_io_q_sam_logon("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAMLOGON, &qbuf, &rbuf)) { + goto done; } - - if (r_s.switch_value != validation_level) { - /* report different switch_value */ - DEBUG(0,("cli_net_sam_logon: switch_value of %x expected %x\n", (unsigned int)validation_level, - (unsigned int)r_s.switch_value)); - retval = NT_STATUS_INVALID_PARAMETER; + + /* Unmarshall response */ + + r.user = &user; + + if (!net_io_r_sam_logon("", &r, &rbuf, 0)) { + goto done; } -out: + /* Return results */ + + result = r.status; - prs_mem_free(&buf); + done: + prs_mem_free(&qbuf); prs_mem_free(&rbuf); - - return retval; + + return result; } -/*************************************************************************** -LSA SAM Logon - interactive or network. -****************************************************************************/ -NTSTATUS cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr, - NET_USER_INFO_3 *user_info3) +/** + * Logon domain user with an 'network' SAM logon + * + * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller. + **/ + +NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, + const char *username, const char *domain, const char *workstation, + const uint8 chal[8], + DATA_BLOB lm_response, DATA_BLOB nt_response, + NET_USER_INFO_3 *info3) + { - uint16 validation_level=3; - NTSTATUS result; + prs_struct qbuf, rbuf; + NET_Q_SAM_LOGON q; + NET_R_SAM_LOGON r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED clnt_creds, dummy_rtn_creds; + NET_ID_INFO_CTR ctr; + extern pstring global_myname; + int validation_level = 3; + char *workstation_name_slash; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); - result = cli_net_sam_logon_internal(cli, ctr, user_info3, - validation_level); + workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); + + if (!workstation_name_slash) { + DEBUG(0, ("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } - if (NT_STATUS_IS_OK(result)) { - DEBUG(10,("cli_net_sam_logon: Success \n")); - } else if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_INVALID_INFO_CLASS)) { - DEBUG(10,("cli_net_sam_logon: STATUS INVALID INFO CLASS \n")); + /* Initialise parse structures */ - validation_level=2; + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* - * Since this is the second time we call this function, don't care - * for the error. If its error, return False. - */ + /* Initialise input parameters */ - result = cli_net_sam_logon_internal(cli, ctr, user_info3, - validation_level); - } + gen_next_creds(cli, &clnt_creds); - return result; -} + q.validation_level = validation_level; -/*************************************************************************** -LSA SAM Logoff. + memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); + dummy_rtn_creds.timestamp.time = time(NULL); -This currently doesnt work correctly as the domain controller -returns NT_STATUS_INVALID_INFO_CLASS - we obviously need to -send a different info level. Right now though, I'm not sure -what that needs to be (I need to see one on the wire before -I can be sure). JRA. -****************************************************************************/ -BOOL cli_net_sam_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr) -{ - DOM_CRED new_clnt_cred; - DOM_CRED dummy_rtn_creds; - prs_struct rbuf; - prs_struct buf; - NET_Q_SAM_LOGOFF q_s; - BOOL ok = False; + ctr.switch_value = NET_LOGON_TYPE; - gen_next_creds( cli, &new_clnt_cred); + init_id_info2(&ctr.auth.id2, domain, + 0, /* param_ctrl */ + 0xdead, 0xbeef, /* LUID? */ + username, workstation_name_slash, (const uchar*)chal, + lm_response.data, lm_response.length, nt_response.data, nt_response.length); + + init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname, + &clnt_creds, &dummy_rtn_creds, NET_LOGON_TYPE, + &ctr); - prs_init(&buf , 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + /* Marshall data and send request */ - /* create and send a MSRPC command with api NET_SAMLOGOFF */ + if (!net_io_q_sam_logon("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, NET_SAMLOGON, &qbuf, &rbuf)) { + goto done; + } - DEBUG(4,("cli_net_sam_logoff: srv:%s mc:%s clnt %s %x ll: %d\n", - cli->srv_name_slash, global_myname, - credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time, - ctr->switch_value)); + /* Unmarshall response */ - memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); + r.user = info3; - init_sam_info(&q_s.sam_id, cli->srv_name_slash, - global_myname, &new_clnt_cred, &dummy_rtn_creds, - ctr->switch_value, ctr); + if (!net_io_r_sam_logon("", &r, &rbuf, 0)) { + goto done; + } + + /* Return results */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/*************************************************************************** +LSA Server Password Set. +****************************************************************************/ - /* turn parameters into data stream */ - if(!net_io_q_sam_logoff("", &q_s, &buf, 0)) { - DEBUG(0,("cli_net_sam_logoff: Error : failed to marshall NET_Q_SAM_LOGOFF struct.\n")); - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } +NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char* machine_name, uint8 hashed_mach_pwd[16]) +{ + prs_struct rbuf; + prs_struct qbuf; + DOM_CRED new_clnt_cred; + NET_Q_SRV_PWSET q_s; + uint16 sec_chan_type = 2; + NTSTATUS nt_status; + char *mach_acct; - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, NET_SAMLOGOFF, &buf, &rbuf)) - { - NET_R_SAM_LOGOFF r_s; + gen_next_creds( cli, &new_clnt_cred); + + prs_init(&qbuf , 1024, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* create and send a MSRPC command with api NET_SRV_PWSET */ + + mach_acct = talloc_asprintf(mem_ctx, "%s$", machine_name); + + if (!mach_acct) { + DEBUG(0,("talloc_asprintf failed!\n")); + nt_status = NT_STATUS_NO_MEMORY; + goto done; + } - ok = net_io_r_sam_logoff("", &r_s, &rbuf, 0); + DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", + cli->srv_name_slash, mach_acct, sec_chan_type, machine_name, + credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); + + /* store the parameters */ + init_q_srv_pwset(&q_s, cli->srv_name_slash, cli->sess_key, + mach_acct, sec_chan_type, machine_name, + &new_clnt_cred, (char *)hashed_mach_pwd); + + /* turn parameters into data stream */ + if(!net_io_q_srv_pwset("", &q_s, &qbuf, 0)) { + DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n")); + nt_status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* send the data on \PIPE\ */ + if (rpc_api_pipe_req(cli, NET_SRVPWSET, &qbuf, &rbuf)) + { + NET_R_SRV_PWSET r_s; + + if (!net_io_r_srv_pwset("", &r_s, &rbuf, 0)) { + nt_status = NT_STATUS_UNSUCCESSFUL; + goto done; + } - if (ok && !NT_STATUS_IS_OK(r_s.status)) - { - /* report error code */ - DEBUG(0,("cli_net_sam_logoff: %s\n", nt_errstr(r_s.status))); - ok = False; - } - - /* Update the credentials. */ - if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds))) - { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_sam_logoff: server %s replied with bad credential (bad machine \ + nt_status = r_s.status; + + if (!NT_STATUS_IS_OK(r_s.status)) + { + /* report error code */ + DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(nt_status))); + goto done; + } + + /* Update the credentials. */ + if (!clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred))) + { + /* + * Server replied with bad credential. Fail. + */ + DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \ password ?).\n", cli->desthost )); - ok = False; - } - } - - prs_mem_free(&buf); - prs_mem_free(&rbuf); + nt_status = NT_STATUS_UNSUCCESSFUL; + } + } - return ok; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return nt_status; } + diff --git a/source3/rpc_client/cli_reg.c b/source3/rpc_client/cli_reg.c index 07001f13bd..aaf18882f7 100644 --- a/source3/rpc_client/cli_reg.c +++ b/source3/rpc_client/cli_reg.c @@ -1,1074 +1,102 @@ /* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1998, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Paul Ashton 1997-1998. - * Copyright (C) Jeremy Allison 1999. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - + Unix SMB/CIFS implementation. + RPC Pipe client + + Copyright (C) Andrew Tridgell 1992-1998, + Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + Copyright (C) Paul Ashton 1997-1998. + Copyright (C) Jeremy Allison 1999. + Copyright (C) Simo Sorce 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_CLI - -/**************************************************************************** -do a REG Open Policy -****************************************************************************/ -BOOL do_reg_connect(struct cli_state *cli, char *full_keyname, char *key_name, - POLICY_HND *reg_hnd) -{ - BOOL res = True; - uint32 reg_type = 0; - - if (full_keyname == NULL) - return False; - - ZERO_STRUCTP(reg_hnd); - - /* - * open registry receive a policy handle - */ - - if (!reg_split_key(full_keyname, ®_type, key_name)) { - DEBUG(0,("do_reg_connect: unrecognised key name %s\n", full_keyname)); - return False; - } - - switch (reg_type) { - case HKEY_LOCAL_MACHINE: - res = res ? do_reg_open_hklm(cli, 0x84E0, 0x02000000, reg_hnd) : False; - break; - - case HKEY_USERS: - res = res ? do_reg_open_hku(cli, 0x84E0, 0x02000000, reg_hnd) : False; - break; - - default: - DEBUG(0,("do_reg_connect: unrecognised hive key\n")); - return False; - } - - return res; -} - -/**************************************************************************** -do a REG Open Policy -****************************************************************************/ -BOOL do_reg_open_hklm(struct cli_state *cli, uint16 unknown_0, uint32 level, - POLICY_HND *hnd) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_OPEN_HKLM q_o; - REG_R_OPEN_HKLM r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_OPEN_HKLM */ - - DEBUG(4,("REG Open HKLM\n")); - - init_reg_q_open_hklm(&q_o, unknown_0, level); - - /* turn parameters into data stream */ - if(!reg_io_q_open_hklm("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_OPEN_HKLM, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_open_hklm("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_OPEN_HKLM: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - /* ok, at last: we're happy. return the policy handle */ - *hnd = r_o.pol; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Open HKU -****************************************************************************/ -BOOL do_reg_open_hku(struct cli_state *cli, uint16 unknown_0, uint32 level, - POLICY_HND *hnd) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_OPEN_HKU q_o; - REG_R_OPEN_HKU r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_OPEN_HKU */ - - DEBUG(4,("REG Open HKU\n")); - - init_reg_q_open_hku(&q_o, unknown_0, level); - - /* turn parameters into data stream */ - if(!reg_io_q_open_hku("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, REG_OPEN_HKU, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_open_hku("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_OPEN_HKU: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - /* ok, at last: we're happy. return the policy handle */ - *hnd = r_o.pol; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Unknown 0xB command. sent after a create key or create value. -this might be some sort of "sync" or "refresh" command, sent after -modification of the registry... -****************************************************************************/ -BOOL do_reg_flush_key(struct cli_state *cli, POLICY_HND *hnd) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_FLUSH_KEY q_o; - REG_R_FLUSH_KEY r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_FLUSH_KEY */ - - DEBUG(4,("REG Unknown 0xB\n")); - - init_reg_q_flush_key(&q_o, hnd); - - /* turn parameters into data stream */ - if(!reg_io_q_flush_key("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_FLUSH_KEY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_flush_key("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_FLUSH_KEY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Query Key -****************************************************************************/ -BOOL do_reg_query_key(struct cli_state *cli, POLICY_HND *hnd, - char *class, uint32 *class_len, - uint32 *num_subkeys, uint32 *max_subkeylen, - uint32 *max_subkeysize, uint32 *num_values, - uint32 *max_valnamelen, uint32 *max_valbufsize, - uint32 *sec_desc, NTTIME *mod_time) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_QUERY_KEY q_o; - REG_R_QUERY_KEY r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_QUERY_KEY */ - - DEBUG(4,("REG Query Key\n")); - - init_reg_q_query_key(&q_o, hnd, *class_len); - - /* turn parameters into data stream */ - if(!reg_io_q_query_key("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_QUERY_KEY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_query_key("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_QUERY_KEY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - *class_len = r_o.hdr_class.uni_max_len; - rpcstr_pull(class, &r_o.uni_class, -1, -1, 0); - *num_subkeys = r_o.num_subkeys ; - *max_subkeylen = r_o.max_subkeylen ; - *max_subkeysize = r_o.max_subkeysize; - *num_values = r_o.num_values ; - *max_valnamelen = r_o.max_valnamelen; - *max_valbufsize = r_o.max_valbufsize; - *sec_desc = r_o.sec_desc ; - *mod_time = r_o.mod_time ; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Unknown 1A -****************************************************************************/ -BOOL do_reg_unknown_1a(struct cli_state *cli, POLICY_HND *hnd, uint32 *unk) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_UNK_1A q_o; - REG_R_UNK_1A r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_UNKNOWN_1A */ - - DEBUG(4,("REG Unknown 1a\n")); - - init_reg_q_unk_1a(&q_o, hnd); - - /* turn parameters into data stream */ - if(!reg_io_q_unk_1a("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, REG_UNK_1A, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_unk_1a("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_UNK_1A: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - (*unk) = r_o.unknown; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Query Info -****************************************************************************/ -BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd, - char *key_value, uint32* key_type) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_INFO q_o; - REG_R_INFO r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_INFO */ - - DEBUG(4,("REG Query Info\n")); - - init_reg_q_info(&q_o, hnd, "ProductType"); - - /* turn parameters into data stream */ - if(!reg_io_q_info("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_INFO, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_info("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if ( r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_INFO: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - /*fstrcpy(key_value, dos_buffer2_to_str(r_o.uni_val));*/ - rpcstr_pull(key_value, r_o.uni_val->buffer, sizeof(fstring), r_o.uni_val->buf_len, 0); - *key_type = r_o.type; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Set Key Security -****************************************************************************/ -BOOL do_reg_set_key_sec(struct cli_state *cli, POLICY_HND *hnd, SEC_DESC_BUF *sec_desc_buf) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_SET_KEY_SEC q_o; - REG_R_SET_KEY_SEC r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_SET_KEY_SEC */ - - DEBUG(4,("REG Set Key security.\n")); - - init_reg_q_set_key_sec(&q_o, hnd, sec_desc_buf); - - /* turn parameters into data stream */ - if(!reg_io_q_set_key_sec("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_SET_KEY_SEC, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_set_key_sec("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Query Key Security -****************************************************************************/ - -BOOL do_reg_get_key_sec(struct cli_state *cli, POLICY_HND *hnd, uint32 *sec_buf_size, SEC_DESC_BUF **ppsec_desc_buf) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_GET_KEY_SEC q_o; - REG_R_GET_KEY_SEC r_o; - - if (hnd == NULL) - return False; +/* Shutdown a server */ - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_GET_KEY_SEC */ - - DEBUG(4,("REG query key security. buf_size: %d\n", *sec_buf_size)); - - init_reg_q_get_key_sec(&q_o, hnd, *sec_buf_size, NULL); - - /* turn parameters into data stream */ - if(!reg_io_q_get_key_sec("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_GET_KEY_SEC, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_get_key_sec("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status == 0x0000007a) { - /* - * get the maximum buffer size: it was too small - */ - (*sec_buf_size) = r_o.hdr_sec.buf_max_len; - DEBUG(5,("sec_buf_size too small. use %d\n", *sec_buf_size)); - } else if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_GET_KEY_SEC: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } else { - (*sec_buf_size) = r_o.data->len; - *ppsec_desc_buf = r_o.data; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Delete Value -****************************************************************************/ -BOOL do_reg_delete_val(struct cli_state *cli, POLICY_HND *hnd, char *val_name) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_DELETE_VALUE q_o; - REG_R_DELETE_VALUE r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_DELETE_VALUE */ - - DEBUG(4,("REG Delete Value: %s\n", val_name)); - - init_reg_q_delete_val(&q_o, hnd, val_name); - - /* turn parameters into data stream */ - if(!reg_io_q_delete_val("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, REG_DELETE_VALUE, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_delete_val("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_DELETE_VALUE: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Delete Key -****************************************************************************/ -BOOL do_reg_delete_key(struct cli_state *cli, POLICY_HND *hnd, char *key_name) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_DELETE_KEY q_o; - REG_R_DELETE_KEY r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_DELETE_KEY */ - - DEBUG(4,("REG Delete Key: %s\n", key_name)); - - init_reg_q_delete_key(&q_o, hnd, key_name); - - /* turn parameters into data stream */ - if(!reg_io_q_delete_key("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_DELETE_KEY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_delete_key("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_DELETE_KEY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Create Key -****************************************************************************/ -BOOL do_reg_create_key(struct cli_state *cli, POLICY_HND *hnd, - char *key_name, char *key_class, - SEC_ACCESS *sam_access, - POLICY_HND *key) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_CREATE_KEY q_o; - REG_R_CREATE_KEY r_o; - SEC_DESC *sec = NULL; - SEC_DESC_BUF *sec_buf = NULL; - size_t sec_len; - - ZERO_STRUCT(q_o); - - if (hnd == NULL) - return False; - - /* create and send a MSRPC command with api REG_CREATE_KEY */ - - DEBUG(4,("REG Create Key: %s %s 0x%08x\n", key_name, key_class, - sam_access != NULL ? sam_access->mask : 0)); - - if((sec = make_sec_desc( cli->mem_ctx, 1, NULL, NULL, NULL, NULL, &sec_len)) == NULL) { - DEBUG(0,("make_sec_desc : malloc fail.\n")); - return False; - } - - DEBUG(10,("make_sec_desc: len = %d\n", (int)sec_len)); - - if((sec_buf = make_sec_desc_buf( cli->mem_ctx, (int)sec_len, sec)) == NULL) { - DEBUG(0,("make_sec_desc : malloc fail (1)\n")); - return False; - } - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - init_reg_q_create_key(&q_o, hnd, key_name, key_class, sam_access, sec_buf); - - /* turn parameters into data stream */ - if(!reg_io_q_create_key("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, REG_CREATE_KEY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_create_key("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_CREATE_KEY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - *key = r_o.key_pol; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Enum Key -****************************************************************************/ -BOOL do_reg_enum_key(struct cli_state *cli, POLICY_HND *hnd, - int key_index, char *key_name, - uint32 *unk_1, uint32 *unk_2, - time_t *mod_time) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_ENUM_KEY q_o; - REG_R_ENUM_KEY r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_ENUM_KEY */ - - DEBUG(4,("REG Enum Key\n")); - - init_reg_q_enum_key(&q_o, hnd, key_index); - - /* turn parameters into data stream */ - if(!reg_io_q_enum_key("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_ENUM_KEY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_enum_key("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_ENUM_KEY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - (*unk_1) = r_o.unknown_1; - (*unk_2) = r_o.unknown_2; - rpcstr_pull(key_name, r_o.key_name.str.buffer, -1, -1, 0); - (*mod_time) = nt_time_to_unix(&r_o.time); - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Create Value -****************************************************************************/ -BOOL do_reg_create_val(struct cli_state *cli, POLICY_HND *hnd, - char *val_name, uint32 type, BUFFER3 *data) +NTSTATUS cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx, + const char *msg, uint32 timeout, uint16 flags) { - prs_struct rbuf; - prs_struct buf; - REG_Q_CREATE_VALUE q_o; - REG_R_CREATE_VALUE r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_CREATE_VALUE */ - - DEBUG(4,("REG Create Value: %s\n", val_name)); - - init_reg_q_create_val(&q_o, hnd, val_name, type, data); - - /* turn parameters into data stream */ - if(!reg_io_q_create_val("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_CREATE_VALUE, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - - if(!reg_io_r_create_val("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_CREATE_VALUE: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Enum Value -****************************************************************************/ -BOOL do_reg_enum_val(struct cli_state *cli, POLICY_HND *hnd, - int val_index, int max_valnamelen, int max_valbufsize, - fstring val_name, - uint32 *val_type, BUFFER2 *value) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_ENUM_VALUE q_o; - REG_R_ENUM_VALUE r_o; + prs_struct qbuf; + prs_struct rbuf; + REG_Q_SHUTDOWN q_s; + REG_R_SHUTDOWN r_s; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (hnd == NULL) - return False; + if (msg == NULL) return NT_STATUS_INVALID_PARAMETER; - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + ZERO_STRUCT (q_s); + ZERO_STRUCT (r_s); - /* create and send a MSRPC command with api REG_ENUM_VALUE */ + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("REG Enum Value\n")); + /* Marshall data and send request */ - init_reg_q_enum_val(&q_o, hnd, val_index, max_valnamelen, max_valbufsize); + init_reg_q_shutdown(&q_s, msg, timeout, flags); - /* turn parameters into data stream */ - if(!reg_io_q_enum_val("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_ENUM_VALUE, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - r_o.buf_value = value; - - if(!reg_io_r_enum_val("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_ENUM_VALUE: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - (*val_type) = r_o.type; - rpcstr_pull(val_name, &r_o.uni_name, -1, -1, 0); + if (!reg_io_q_shutdown("", &q_s, &qbuf, 0) || + !rpc_api_pipe_req(cli, REG_SHUTDOWN, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if(reg_io_r_shutdown("", &r_s, &rbuf, 0)) + result = r_s.status; +done: prs_mem_free(&rbuf); + prs_mem_free(&qbuf); - return True; + return result; } -/**************************************************************************** -do a REG Open Key -****************************************************************************/ -BOOL do_reg_open_entry(struct cli_state *cli, POLICY_HND *hnd, - char *key_name, uint32 unk_0, - POLICY_HND *key_hnd) -{ - prs_struct rbuf; - prs_struct buf; - REG_Q_OPEN_ENTRY q_o; - REG_R_OPEN_ENTRY r_o; - - if (hnd == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api REG_OPEN_ENTRY */ - - DEBUG(4,("REG Open Entry\n")); - - init_reg_q_open_entry(&q_o, hnd, key_name, unk_0); - - /* turn parameters into data stream */ - if(!reg_io_q_open_entry("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_OPEN_ENTRY, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_o); - if(!reg_io_r_open_entry("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } +/* Abort a server shutdown */ - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("REG_OPEN_ENTRY: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return False; - } - - *key_hnd = r_o.pol; - - prs_mem_free(&rbuf); - - return True; -} - -/**************************************************************************** -do a REG Close -****************************************************************************/ -BOOL do_reg_close(struct cli_state *cli, POLICY_HND *hnd) +NTSTATUS cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx) { prs_struct rbuf; - prs_struct buf; - REG_Q_CLOSE q_c; - REG_R_CLOSE r_c; - - if (hnd == NULL) - return False; - - /* create and send a MSRPC command with api REG_CLOSE */ - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); + prs_struct qbuf; + REG_Q_ABORT_SHUTDOWN q_s; + REG_R_ABORT_SHUTDOWN r_s; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DEBUG(4,("REG Close\n")); + ZERO_STRUCT (q_s); + ZERO_STRUCT (r_s); - /* store the parameters */ - init_reg_q_close(&q_c, hnd); - - /* turn parameters into data stream */ - if(!reg_io_q_close("", &q_c, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, REG_CLOSE, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return False; - } - - prs_mem_free(&buf); - - ZERO_STRUCT(r_c); - - if(!reg_io_r_close("", &r_c, &rbuf, 0)) { - prs_mem_free(&rbuf); - return False; - } - - if (r_c.status != 0) { - /* report error code */ - DEBUG(0,("REG_CLOSE: %s\n", nt_errstr(r_c.status))); - prs_mem_free(&rbuf); - return False; - } + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ - /* check that the returned policy handle is all zeros */ + init_reg_q_abort_shutdown(&q_s); - if (IVAL(&r_c.pol.data1,0) || IVAL(&r_c.pol.data2,0) || SVAL(&r_c.pol.data3,0) || - SVAL(&r_c.pol.data4,0) || IVAL(r_c.pol.data5,0) || IVAL(r_c.pol.data5,4) ) { - prs_mem_free(&rbuf); - DEBUG(0,("REG_CLOSE: non-zero handle returned\n")); - return False; - } + if (!reg_io_q_abort_shutdown("", &q_s, &qbuf, 0) || + !rpc_api_pipe_req(cli, REG_ABORT_SHUTDOWN, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (reg_io_r_abort_shutdown("", &r_s, &rbuf, 0)) + result = r_s.status; +done: prs_mem_free(&rbuf); + prs_mem_free(&qbuf ); - return True; + return result; } diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 0d4db7f88f..7863d32419 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -1,9 +1,12 @@ /* Unix SMB/CIFS implementation. - NT Domain Authentication SMB / MSRPC client - Copyright (C) Andrew Tridgell 1994-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Jeremy Allison 1999. + RPC pipe client + Copyright (C) Tim Potter 2000-2001, + Copyright (C) Andrew Tridgell 1992-1997,2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000, + Copyright (C) Paul Ashton 1997,2000, + Copyright (C) Elrond 2000, + Copyright (C) Rafal Szczesniak 2002. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,819 +25,1427 @@ #include "includes.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_CLI +/* Connect to SAMR database */ -/**************************************************************************** -do a SAMR query user groups -****************************************************************************/ -BOOL get_samr_query_usergroups(struct cli_state *cli, - POLICY_HND *pol_open_domain, uint32 user_rid, - uint32 *num_groups, DOM_GID *gid) +NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 access_mask, POLICY_HND *connect_pol) { - POLICY_HND pol_open_user; - if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) - return False; + prs_struct qbuf, rbuf; + SAMR_Q_CONNECT q; + SAMR_R_CONNECT r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - /* send open domain (on user sid) */ - if (!do_samr_open_user(cli, - pol_open_domain, - 0x02011b, user_rid, - &pol_open_user)) - { - return False; - } + 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); + + /* Marshall data and send request */ + + init_samr_q_connect(&q, cli->desthost, access_mask); + + if (!samr_io_q_connect("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) + goto done; - /* send user groups query */ - if (!do_samr_query_usergroups(cli, - &pol_open_user, - num_groups, gid)) - { - DEBUG(5,("do_samr_query_usergroups: error in query user groups\n")); + /* Unmarshall response */ + + if (!samr_io_r_connect("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *connect_pol = r.connect_pol; +#ifdef __INSURE__ + connect_pol->marker = malloc(1); +#endif } - return do_samr_close(cli, &pol_open_user); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -#if 0 -/* DOES NOT COMPILE WITH THE NEW SAMR PARSE CODE. JRA. */ +/* Connect to SAMR database */ -/**************************************************************************** -do a SAMR query user info -****************************************************************************/ -BOOL get_samr_query_userinfo(struct cli_state *cli, - POLICY_HND *pol_open_domain, - uint32 info_level, - uint32 user_rid, SAM_USER_INFO_21 *usr) +NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 access_mask, POLICY_HND *connect_pol) { - POLICY_HND pol_open_user; - if (pol_open_domain == NULL || usr == NULL) - return False; + prs_struct qbuf, rbuf; + SAMR_Q_CONNECT4 q; + SAMR_R_CONNECT4 r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - memset((char *)usr, '\0', sizeof(*usr)); + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* send open domain (on user sid) */ - if (!do_samr_open_user(cli, - pol_open_domain, - 0x02011b, user_rid, - &pol_open_user)) - { - return False; - } + /* Initialise parse structures */ - /* send user info query */ - if (!do_samr_query_userinfo(cli, - &pol_open_user, - info_level, (void*)usr)) - { - DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n", - info_level)); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_connect4(&q, cli->desthost, access_mask); + + if (!samr_io_q_connect4("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_CONNECT4, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_connect4("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *connect_pol = r.connect_pol; +#ifdef __INSURE__ + connect_pol->marker = malloc(1); +#endif } - return do_samr_close(cli, &pol_open_user); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -#endif -/**************************************************************************** -do a SAMR change user password command -****************************************************************************/ -BOOL do_samr_chgpasswd_user(struct cli_state *cli, - char *srv_name, char *user_name, - char nt_newpass[516], uchar nt_oldhash[16], - char lm_newpass[516], uchar lm_oldhash[16]) +/* Close SAMR handle */ + +NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *connect_pol) { - prs_struct data; - prs_struct rdata; - SAMR_Q_CHGPASSWD_USER q_e; - SAMR_R_CHGPASSWD_USER r_e; + prs_struct qbuf, rbuf; + SAMR_Q_CLOSE_HND q; + SAMR_R_CLOSE_HND r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - /* create and send a MSRPC command with api SAMR_CHGPASSWD_USER */ + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + /* Initialise parse structures */ - DEBUG(4,("SAMR Change User Password. server:%s username:%s\n", - srv_name, user_name)); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - init_samr_q_chgpasswd_user(&q_e, srv_name, user_name, - nt_newpass, nt_oldhash, - lm_newpass, lm_oldhash); + /* Marshall data and send request */ - /* turn parameters into data stream */ - if(!samr_io_q_chgpasswd_user("", &q_e, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + init_samr_q_close_hnd(&q, connect_pol); + + if (!samr_io_q_close_hnd("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { +#ifdef __INSURE__ + SAFE_FREE(connect_pol->marker); +#endif + *connect_pol = r.pol; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_CHGPASSWD_USER, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Open handle on a domain */ + +NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *connect_pol, uint32 access_mask, + const DOM_SID *domain_sid, POLICY_HND *domain_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_OPEN_DOMAIN q; + SAMR_R_OPEN_DOMAIN r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid); + + if (!samr_io_q_open_domain("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_open_domain("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *domain_pol = r.domain_pol; +#ifdef __INSURE__ + domain_pol->marker = malloc(1); +#endif } - prs_mem_free(&data); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - if(!samr_io_r_chgpasswd_user("", &r_e, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + return result; +} + +/* Open handle on a user */ + +NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 user_rid, POLICY_HND *user_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_OPEN_USER q; + SAMR_R_OPEN_USER r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_open_user(&q, domain_pol, access_mask, user_rid); + + if (!samr_io_q_open_user("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_open_user("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *user_pol = r.user_pol; +#ifdef __INSURE__ + user_pol->marker = malloc(1); +#endif } - if (r_e.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_CHGPASSWD_USER: %s\n", nt_errstr(r_e.status))); - prs_mem_free(&rdata); - return False; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Open handle on a group */ + +NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 group_rid, POLICY_HND *group_pol) +{ + prs_struct qbuf, rbuf; + SAMR_Q_OPEN_GROUP q; + SAMR_R_OPEN_GROUP r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_open_group(&q, domain_pol, access_mask, group_rid); + + if (!samr_io_q_open_group("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_open_group("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *group_pol = r.pol; +#ifdef __INSURE__ + group_pol->marker = malloc(1); +#endif } - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#if 0 +/* Query user info */ + +NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint16 switch_value, + SAM_USERINFO_CTR **ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_USERINFO q; + SAMR_R_QUERY_USERINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_query_userinfo(&q, user_pol, switch_value); + + if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) + goto done; -/* CURRENTLY THIS DOESN'T COMPILE AND IS NOT USED ANYWHERE. JRA. */ + /* Return output parameters */ -/**************************************************************************** -do a SAMR unknown 0x38 command -****************************************************************************/ -BOOL do_samr_unknown_38(struct cli_state *cli, char *srv_name) + result = r.status; + *ctr = r.ctr; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query group info */ + +NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *group_pol, uint32 info_level, + GROUP_INFO_CTR *ctr) { - prs_struct data; - prs_struct rdata; + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_GROUPINFO q; + SAMR_R_QUERY_GROUPINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - SAMR_Q_UNKNOWN_38 q_e; - SAMR_R_UNKNOWN_38 r_e; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Unknown 38 server:%s\n", srv_name)); + /* Marshall data and send request */ - init_samr_q_unknown_38(&q_e, srv_name); + init_samr_q_query_groupinfo(&q, group_pol, info_level); - /* turn parameters into data stream */ - if(!samr_io_q_unknown_38("", &q_e, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) + goto done; - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_UNKNOWN_38, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + /* Unmarshall response */ - prs_mem_free(&data); + r.ctr = ctr; - if(!samr_io_r_unknown_38("", &r_e, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query user groups */ + +NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint32 *num_groups, + DOM_GID **gid) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_USERGROUPS q; + SAMR_R_QUERY_USERGROUPS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_query_usergroups(&q, user_pol); + + if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *num_groups = r.num_entries; + *gid = r.gid; } - if (r_e.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_UNKNOWN_38: %s\n", nt_errstr(r_e.status))); - prs_mem_free(&rdata); - return False; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query user aliases */ + +NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint32 num_sids, DOM_SID2 *sid, + uint32 *num_aliases, uint32 **als_rids) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_USERALIASES q; + SAMR_R_QUERY_USERALIASES r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + unsigned int ptr=1; + + 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); + + /* Marshall data and send request */ + + init_samr_q_query_useraliases(&q, user_pol, num_sids, &ptr, sid); + + if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_query_useraliases("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *num_aliases = r.num_entries; + *als_rids = r.rid; } - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#endif -/**************************************************************************** -do a SAMR unknown 0x8 command -****************************************************************************/ -BOOL do_samr_query_dom_info(struct cli_state *cli, - POLICY_HND *domain_pol, uint16 switch_value) +/* Query user groups */ + +NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *group_pol, uint32 *num_mem, + uint32 **rid, uint32 **attr) { - prs_struct data; - prs_struct rdata; - SAMR_Q_QUERY_DOMAIN_INFO q_e; - SAMR_R_QUERY_DOMAIN_INFO r_e; + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_GROUPMEM q; + SAMR_R_QUERY_GROUPMEM r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (domain_pol == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_query_dom_info(&q_e, domain_pol, switch_value); + init_samr_q_query_groupmem(&q, group_pol); - /* turn parameters into data stream */ - if(!samr_io_q_query_dom_info("", &q_e, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *num_mem = r.num_entries; + *rid = r.rid; + *attr = r.attr; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &data, &rdata)) { - prs_mem_free(&data); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/** + * Enumerate domain users + * + * @param cli client state structure + * @param mem_ctx talloc context + * @param pol opened domain policy handle + * @param start_idx starting index of enumeration, returns context for + next enumeration + * @param acb_mask account control bit mask (to enumerate some particular + * kind of accounts) + * @param size max acceptable size of response + * @param dom_users returned array of domain user names + * @param rids returned array of domain user RIDs + * @param num_dom_users numer returned entries + * + * @return NTSTATUS returned in rpc response + **/ +NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask, + uint32 size, char ***dom_users, uint32 **rids, + uint32 *num_dom_users) +{ + prs_struct qdata; + prs_struct rdata; + SAMR_Q_ENUM_DOM_USERS q; + SAMR_R_ENUM_DOM_USERS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + int i; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + if (cli == NULL || pol == NULL) + return result; + + /* initialise parse structures */ + prs_init(&qdata, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rdata, 0, mem_ctx, UNMARSHALL); + + DEBUG(4, ("SAMR Enum Domain Users. start_idx: %d, acb: %d, size: %d\n", + *start_idx, acb_mask, size)); + + /* fill query structure with parameters */ + init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size); + + /* prepare query stream */ + if (!samr_io_q_enum_dom_users("", &q, &qdata, 0)) { + prs_mem_free(&qdata); + prs_mem_free(&rdata); + return result; + } + + /* send rpc call over the pipe */ + if (!rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &qdata, &rdata)) { + prs_mem_free(&qdata); + prs_mem_free(&rdata); + return result; + } + + /* unpack received stream */ + if(!samr_io_r_enum_dom_users("", &r, &rdata, 0)) { + prs_mem_free(&qdata); prs_mem_free(&rdata); - return False; + result = r.status; + return result; } + + /* return the data obtained in response */ + if (!NT_STATUS_IS_OK(r.status) && + (NT_STATUS_EQUAL(r.status, STATUS_MORE_ENTRIES) || + NT_STATUS_EQUAL(r.status, NT_STATUS_NO_MORE_ENTRIES))) { + return r.status; + } + + *start_idx = r.next_idx; + *num_dom_users = r.num_entries2; + result = r.status; + + if (r.num_entries2) { + /* allocate memory needed to return received data */ + *rids = (uint32*)talloc(mem_ctx, sizeof(uint32) * r.num_entries2); + if (!*rids) { + DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n")); + return NT_STATUS_NO_MEMORY; + } + + *dom_users = (char**)talloc(mem_ctx, sizeof(char*) * r.num_entries2); + if (!*dom_users) { + DEBUG(0, ("Error in cli_samr_enum_dom_users(): out of memory\n")); + return NT_STATUS_NO_MEMORY; + } + + /* fill output buffers with rpc response */ + for (i = 0; i < r.num_entries2; i++) { + fstring conv_buf; + + (*rids)[i] = r.sam[i].rid; + unistr2_to_ascii(conv_buf, &(r.uni_acct_name[i]), sizeof(conv_buf) - 1); + (*dom_users)[i] = talloc_strdup(mem_ctx, conv_buf); + } + } + + prs_mem_free(&qdata); + prs_mem_free(&rdata); + + return result; +}; - prs_mem_free(&data); - if(!samr_io_r_query_dom_info("", &r_e, &rdata, 0)) { - prs_mem_free(&rdata); - return False; +/* Enumerate domain groups */ + +NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 *start_idx, + uint32 size, struct acct_info **dom_groups, + uint32 *num_dom_groups) +{ + prs_struct qbuf, rbuf; + SAMR_Q_ENUM_DOM_GROUPS q; + SAMR_R_ENUM_DOM_GROUPS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 name_idx, 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); + + /* Marshall data and send request */ + + init_samr_q_enum_dom_groups(&q, pol, *start_idx, size); + + if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (!NT_STATUS_IS_OK(result) && + NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) + goto done; + + *num_dom_groups = r.num_entries2; + + if (!((*dom_groups) = (struct acct_info *) + talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - if (r_e.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_QUERY_DOMAIN_INFO: %s\n", nt_errstr(r_e.status))); - prs_mem_free(&rdata); - return False; + memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups); + + name_idx = 0; + + for (i = 0; i < *num_dom_groups; i++) { + + (*dom_groups)[i].rid = r.sam[i].rid; + + if (r.sam[i].hdr_name.buffer) { + unistr2_to_ascii((*dom_groups)[i].acct_name, + &r.uni_grp_name[name_idx], + sizeof(fstring) - 1); + name_idx++; + } + + *start_idx = r.next_idx; } - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#if 0 +/* Enumerate domain groups */ -/* CURRENTLY DOESN'T COMPILE WITH THE NEW SAMR PARSE CODE. JRA */ - -/**************************************************************************** -do a SAMR enumerate users -****************************************************************************/ -BOOL do_samr_enum_dom_users(struct cli_state *cli, - POLICY_HND *pol, uint16 num_entries, uint16 unk_0, - uint16 acb_mask, uint16 unk_1, uint32 size, - struct acct_info **sam, - int *num_sam_users) +NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 *start_idx, + uint32 size, struct acct_info **dom_groups, + uint32 *num_dom_groups) { - prs_struct data; - prs_struct rdata; - SAMR_Q_ENUM_DOM_USERS q_e; - SAMR_R_ENUM_DOM_USERS r_e; - int i; - int name_idx = 0; + prs_struct qbuf, rbuf; + SAMR_Q_ENUM_DOM_ALIASES q; + SAMR_R_ENUM_DOM_ALIASES r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 name_idx, i; - if (pol == NULL || num_sam_users == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_enum_dom_users(&q_e, pol, - num_entries, unk_0, - acb_mask, unk_1, size); + init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size); - /* turn parameters into data stream */ - if(!samr_io_q_enum_dom_users("", &q_e, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_enum_dom_aliases("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_ALIASES, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_ENUM_DOM_USERS, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_enum_dom_aliases("", &r, &rbuf, 0)) { + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - if(!samr_io_r_enum_dom_users("", &r_e, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } + result = r.status; - if (r_e.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", nt_errstr(r_e.status))); - prs_mem_free(&rdata); - return False; + if (!NT_STATUS_IS_OK(result) && + NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) { + goto done; } - *num_sam_users = r_e.num_entries2; - if (*num_sam_users > MAX_SAM_ENTRIES) { - *num_sam_users = MAX_SAM_ENTRIES; - DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n", - *num_sam_users)); + *num_dom_groups = r.num_entries2; + + if (!((*dom_groups) = (struct acct_info *) + talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - *sam = (struct acct_info*) malloc(sizeof(struct acct_info) * (*num_sam_users)); - - if ((*sam) == NULL) - *num_sam_users = 0; + memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups); + + name_idx = 0; + + for (i = 0; i < *num_dom_groups; i++) { - for (i = 0; i < *num_sam_users; i++) { - (*sam)[i].smb_userid = r_e.sam[i].rid; - if (r_e.sam[i].hdr_name.buffer) { - char *acct_name = dos_unistrn2(r_e.uni_acct_name[name_idx].buffer, - r_e.uni_acct_name[name_idx].uni_str_len); - fstrcpy((*sam)[i].acct_name, acct_name); + (*dom_groups)[i].rid = r.sam[i].rid; + + if (r.sam[i].hdr_name.buffer) { + unistr2_to_ascii((*dom_groups)[i].acct_name, + &r.uni_grp_name[name_idx], + sizeof(fstring) - 1); name_idx++; - } else { - memset((char *)(*sam)[i].acct_name, '\0', sizeof((*sam)[i].acct_name)); } - DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n", - i, (*sam)[i].smb_userid, (*sam)[i].acct_name)); + *start_idx = r.next_idx; } - prs_mem_free(&rdata ); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#endif -/**************************************************************************** -do a SAMR Connect -****************************************************************************/ -BOOL do_samr_connect(struct cli_state *cli, - char *srv_name, uint32 unknown_0, - POLICY_HND *connect_pol) +/* Query alias members */ + +NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *alias_pol, uint32 *num_mem, + DOM_SID **sids) { - prs_struct data; - prs_struct rdata; - SAMR_Q_CONNECT q_o; - SAMR_R_CONNECT r_o; + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_ALIASMEM q; + SAMR_R_QUERY_ALIASMEM r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 i; - if (srv_name == NULL || connect_pol == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_CONNECT */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n", - srv_name, unknown_0)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_connect(&q_o, srv_name, unknown_0); + init_samr_q_query_aliasmem(&q, alias_pol); - /* turn parameters into data stream */ - if(!samr_io_q_connect("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_CONNECT, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) { + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - if(!samr_io_r_connect("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_CONNECT: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + + *num_mem = r.num_sids; + + if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol)); + for (i = 0; i < *num_mem; i++) { + (*sids)[i] = r.sid[i].sid; + } - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -/**************************************************************************** -do a SAMR Open User -****************************************************************************/ -BOOL do_samr_open_user(struct cli_state *cli, - POLICY_HND *pol, uint32 unk_0, uint32 rid, - POLICY_HND *user_pol) +/* Open handle on an alias */ + +NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 alias_rid, POLICY_HND *alias_pol) { - prs_struct data; - prs_struct rdata; - SAMR_Q_OPEN_USER q_o; - SAMR_R_OPEN_USER r_o; + prs_struct qbuf, rbuf; + SAMR_Q_OPEN_ALIAS q; + SAMR_R_OPEN_ALIAS r; + NTSTATUS result; - if (pol == NULL || user_pol == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_OPEN_USER */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Open User. unk_0: %08x RID:%x\n", - unk_0, rid)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_open_user(&q_o, pol, unk_0, rid); + init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid); - /* turn parameters into data stream */ - if(!samr_io_q_open_user("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_open_alias("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_OPEN_USER, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_open_alias("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - if(!samr_io_r_open_user("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (NT_STATUS_IS_OK(result = r.status)) { + *alias_pol = r.pol; +#ifdef __INSURE__ + alias_pol->marker = malloc(1); +#endif } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_OPEN_USER: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query domain info */ + +NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint16 switch_value, + SAM_UNK_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_DOMAIN_INFO q; + SAMR_R_QUERY_DOMAIN_INFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_query_dom_info(&q, domain_pol, switch_value); + + if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) { + goto done; } - memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol)); + /* Unmarshall response */ - prs_mem_free(&rdata); + r.ctr = ctr; + + if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ - return True; + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/**************************************************************************** -do a SAMR Open Domain -****************************************************************************/ -BOOL do_samr_open_domain(struct cli_state *cli, - POLICY_HND *connect_pol, uint32 rid, DOM_SID *sid, - POLICY_HND *domain_pol) +/* Query display info */ + +NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 *start_idx, + uint16 switch_value, uint32 *num_entries, + uint32 max_entries, SAM_DISPINFO_CTR *ctr) { - prs_struct data; - prs_struct rdata; - pstring sid_str; - SAMR_Q_OPEN_DOMAIN q_o; - SAMR_R_OPEN_DOMAIN r_o; + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_DISPINFO q; + SAMR_R_QUERY_DISPINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (connect_pol == NULL || sid == NULL || domain_pol == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - sid_to_string(sid_str, sid); - DEBUG(4,("SAMR Open Domain. SID:%s RID:%x\n", sid_str, rid)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_open_domain(&q_o, connect_pol, rid, sid); + init_samr_q_query_dispinfo(&q, domain_pol, switch_value, + *start_idx, max_entries); - /* turn parameters into data stream */ - if(!samr_io_q_open_domain("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + /* Unmarshall response */ - prs_mem_free(&data); + r.ctr = ctr; - if(!samr_io_r_open_domain("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) { + goto done; } - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + /* Return output parameters */ + + result = r.status; + + if (!NT_STATUS_IS_OK(result) && + NT_STATUS_V(result) != NT_STATUS_V(STATUS_MORE_ENTRIES)) { + goto done; } - memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol)); + *num_entries = r.num_entries; + *start_idx += r.num_entries; /* No next_idx in this structure! */ - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#if 0 - -/* CURRENTLY DOES NOT COMPILE AND IS NOT USED ANYWHERE. JRA. */ +/* Lookup rids. Note that NT4 seems to crash if more than ~1000 rids are + looked up in one packet. */ -/**************************************************************************** -do a SAMR Query Unknown 12 -****************************************************************************/ -BOOL do_samr_query_unknown_12(struct cli_state *cli, - POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids, - uint32 *num_aliases, - fstring als_names [MAX_LOOKUP_SIDS], - uint32 num_als_users[MAX_LOOKUP_SIDS]) +NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 flags, + uint32 num_rids, uint32 *rids, + uint32 *num_names, char ***names, + uint32 **name_types) { - prs_struct data; - prs_struct rdata; - SAMR_Q_LOOKUP_RIDS q_o; - SAMR_R_LOOKUP_RIDS r_o; + prs_struct qbuf, rbuf; + SAMR_Q_LOOKUP_RIDS q; + SAMR_R_LOOKUP_RIDS r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 i; - if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL || - num_aliases == NULL || als_names == NULL || num_als_users == NULL ) - return False; + if (num_rids > 1000) { + DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if " + "more than ~1000 rids are looked up at once.\n")); + } - /* create and send a MSRPC command with api SAMR_UNKNOWN_12 */ + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + /* Initialise parse structures */ - DEBUG(4,("SAMR Query Unknown 12.\n")); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* store the parameters */ - init_samr_q_lookup_rids(&q_o, pol, rid, num_gids, gids); + /* Marshall data and send request */ - /* turn parameters into data stream */ - if(!samr_io_q_lookup_rids("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags, + num_rids, rids); + + if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) { + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - if(!samr_io_r_lookup_rids("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + + if (r.num_names1 == 0) { + *num_names = 0; + *names = NULL; + goto done; } - if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 && - r_o.num_als_usrs1 == r_o.num_aliases1) { - int i; + *num_names = r.num_names1; + *names = talloc(mem_ctx, sizeof(char *) * r.num_names1); + *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1); - *num_aliases = r_o.num_aliases1; + for (i = 0; i < r.num_names1; i++) { + fstring tmp; - for (i = 0; i < r_o.num_aliases1; i++) { - fstrcpy(als_names[i], dos_unistrn2(r_o.uni_als_name[i].buffer, - r_o.uni_als_name[i].uni_str_len)); - } - for (i = 0; i < r_o.num_als_usrs1; i++) { - num_als_users[i] = r_o.num_als_usrs[i]; - } - } else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0) { - *num_aliases = 0; - } else { - prs_mem_free(&rdata); - return False; + unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1); + (*names)[i] = talloc_strdup(mem_ctx, tmp); + (*name_types)[i] = r.type[i]; } - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } -#endif -/**************************************************************************** -do a SAMR Query User Groups -****************************************************************************/ -BOOL do_samr_query_usergroups(struct cli_state *cli, - POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid) +/* Lookup names */ + +NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 flags, + uint32 num_names, const char **names, + uint32 *num_rids, uint32 **rids, + uint32 **rid_types) { - prs_struct data; - prs_struct rdata; - SAMR_Q_QUERY_USERGROUPS q_o; - SAMR_R_QUERY_USERGROUPS r_o; + prs_struct qbuf, rbuf; + SAMR_Q_LOOKUP_NAMES q; + SAMR_R_LOOKUP_NAMES r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 i; - if (pol == NULL || gid == NULL || num_groups == 0) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Query User Groups.\n")); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_query_usergroups(&q_o, pol); + init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags, + num_names, names); - /* turn parameters into data stream */ - if(!samr_io_q_query_usergroups("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_lookup_names("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + /* Unmarshall response */ - prs_mem_free(&data); + if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) { + goto done; + } - /* get user info */ - r_o.gid = gid; + /* Return output parameters */ - if(!samr_io_r_query_usergroups("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + + if (r.num_rids1 == 0) { + *num_rids = 0; + goto done; } - *num_groups = r_o.num_entries; + *num_rids = r.num_rids1; + *rids = talloc(mem_ctx, sizeof(uint32) * r.num_rids1); + *rid_types = talloc(mem_ctx, sizeof(uint32) * r.num_rids1); - prs_mem_free(&rdata); + for (i = 0; i < r.num_rids1; i++) { + (*rids)[i] = r.rids[i]; + (*rid_types)[i] = r.types[i]; + } - return True; -} + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); -#if 0 + return result; +} -/* CURRENTLY DOES NOT COMPILE WITH THE NEW SAMR PARSE CODE. JRA */ +/* Create a domain user */ -/**************************************************************************** -do a SAMR Query User Info -****************************************************************************/ -BOOL do_samr_query_userinfo(struct cli_state *cli, - POLICY_HND *pol, uint16 switch_value, void* usr) +NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, const char *acct_name, + uint32 acb_info, uint32 unknown, + POLICY_HND *user_pol, uint32 *rid) { - prs_struct data; - prs_struct rdata; - SAMR_Q_QUERY_USERINFO q_o; - SAMR_R_QUERY_USERINFO r_o; + prs_struct qbuf, rbuf; + SAMR_Q_CREATE_USER q; + SAMR_R_CREATE_USER r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (pol == NULL || usr == NULL || switch_value == 0) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* create and send a MSRPC command with api SAMR_QUERY_USERINFO */ + /* Initialise parse structures */ - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Query User Info. level: %d\n", switch_value)); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_query_userinfo(&q_o, pol, switch_value); + init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown); - /* turn parameters into data stream */ - if(!samr_io_q_query_userinfo("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_create_user("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_CREATE_USER, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_create_user("", &r, &rbuf, 0)) { + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - /* get user info */ - r_o.info.id = usr; + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } - if(!samr_io_r_query_userinfo("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + if (user_pol) + *user_pol = r.user_pol; + + if (rid) + *rid = r.user_rid; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Set userinfo */ + +NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint16 switch_value, + uchar sess_key[16], SAM_USERINFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_SET_USERINFO q; + SAMR_R_SET_USERINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + q.ctr = ctr; + + init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, + ctr->info.id); + + if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_SET_USERINFO, &qbuf, &rbuf)) { + goto done; } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + + /* Unmarshall response */ + + if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) { + goto done; } - if (r_o.switch_value != switch_value) { - DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n", - r_o.switch_value)); - prs_mem_free(&rdata); - return False; + /* Return output parameters */ + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; } - if (r_o.ptr == 0) { - prs_mem_free(&rdata); - return False; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Set userinfo2 */ + +NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint16 switch_value, + uchar sess_key[16], SAM_USERINFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_SET_USERINFO2 q; + SAMR_R_SET_USERINFO2 r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr); + + if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_SET_USERINFO2, &qbuf, &rbuf)) { + goto done; } - prs_mem_free(&rdata); + /* Unmarshall response */ - return True; + if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -#endif +/* Delete domain user */ -/**************************************************************************** -do a SAMR Close -****************************************************************************/ -BOOL do_samr_close(struct cli_state *cli, POLICY_HND *hnd) +NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol) { - prs_struct data; - prs_struct rdata; - SAMR_Q_CLOSE_HND q_c; - SAMR_R_CLOSE_HND r_c; + prs_struct qbuf, rbuf; + SAMR_Q_DELETE_DOM_USER q; + SAMR_R_DELETE_DOM_USER r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (hnd == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + /* Initialise parse structures */ - /* create and send a MSRPC command with api SAMR_CLOSE_HND */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SAMR Close\n")); + /* Marshall data and send request */ - /* store the parameters */ - init_samr_q_close_hnd(&q_c, hnd); + init_samr_q_delete_dom_user(&q, user_pol); - /* turn parameters into data stream */ - if(!samr_io_q_close_hnd("", &q_c, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) { + goto done; } - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) { + goto done; } - prs_mem_free(&data); + /* Return output parameters */ - if(!samr_io_r_close_hnd("", &r_c, &rdata, 0)) { - prs_mem_free(&rdata); - return False; + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Query user security object */ + +NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *user_pol, uint16 switch_value, + TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_SEC_OBJ q; + SAMR_R_QUERY_SEC_OBJ r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_query_sec_obj(&q, user_pol, switch_value); + + if (!samr_io_q_query_sec_obj("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_SEC_OBJECT, &qbuf, &rbuf)) { + goto done; } - if (r_c.status != 0) { - /* report error code */ - DEBUG(0,("SAMR_CLOSE_HND: %s\n", nt_errstr(r_c.status))); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + if (!samr_io_r_query_sec_obj("", &r, &rbuf, 0)) { + goto done; } - /* check that the returned policy handle is all zeros */ + /* Return output parameters */ - if (IVAL(&r_c.pol.data1,0) || IVAL(&r_c.pol.data2,0) || SVAL(&r_c.pol.data3,0) || - SVAL(&r_c.pol.data4,0) || IVAL(r_c.pol.data5,0) || IVAL(r_c.pol.data5,4) ) { - DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n")); - prs_mem_free(&rdata); - return False; - } + result = r.status; + *sec_desc_buf=dup_sec_desc_buf(ctx, r.buf); - prs_mem_free(&rdata); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Get domain password info */ + +NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint16 *unk_0, uint16 *unk_1, uint16 *unk_2) +{ + prs_struct qbuf, rbuf; + SAMR_Q_GET_DOM_PWINFO q; + SAMR_R_GET_DOM_PWINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + 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); + + /* Marshall data and send request */ + + init_samr_q_get_dom_pwinfo(&q, cli->desthost); + + if (!samr_io_q_get_dom_pwinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_GET_DOM_PWINFO, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!samr_io_r_get_dom_pwinfo("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (NT_STATUS_IS_OK(result)) { + if (unk_0) + *unk_0 = r.unk_0; + if (unk_1) + *unk_1 = r.unk_1; + if (unk_2) + *unk_2 = r.unk_2; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return True; + return result; } diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index 5292569ed4..18e17758d6 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -1,820 +1,2156 @@ /* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-2000, - * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, - * Copyright (C) Paul Ashton 1997-2000, - * Copyright (C) Jean Francois Micouleau 1998-2000, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Gerald Carter 2001-2002, + Copyright (C) Tim Potter 2000-2002, + Copyright (C) Andrew Tridgell 1994-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Jean-Francois Micouleau 1999-2000. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -#include "rpc_parse.h" -#include "nterr.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_CLI - -/**************************************************************************** -do a SPOOLSS Enum Printer Drivers -****************************************************************************/ -uint32 spoolss_enum_printerdrivers(const char *srv_name, const char *environment, - uint32 level, NEW_BUFFER *buffer, uint32 offered, - uint32 *needed, uint32 *returned) -{ - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_ENUMPRINTERDRIVERS q_o; - SPOOL_R_ENUMPRINTERDRIVERS r_o; - TALLOC_CTX *ctx = prs_get_mem_context(&buffer->prs); - - struct cli_connection *con = NULL; - - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */ - - DEBUG(5,("SPOOLSS Enum Printer Drivers (Server: %s Environment: %s level: %d)\n", - srv_name, environment, level)); - - make_spoolss_q_enumprinterdrivers(&q_o, srv_name, environment, - level, buffer, offered); - - /* turn parameters into data stream */ - if (spoolss_io_q_enumprinterdrivers("", &q_o, &buf, 0) && - rpc_con_pipe_req(con, SPOOLSS_ENUMPRINTERDRIVERS, &buf, &rbuf)) - { - prs_mem_free(&buf); - ZERO_STRUCT(r_o); - - prs_switch_type(&buffer->prs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; - - if(spoolss_io_r_enumprinterdrivers("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_ENUMPRINTERDRIVERS: %s\n", nt_errstr(r_o.status))); - } - *needed=r_o.needed; - *returned=r_o.returned; - } - } - prs_mem_free(&rbuf); - prs_mem_free(&buf ); - - cli_connection_unlink(con); +/** @defgroup spoolss SPOOLSS - NT printing routines + * @ingroup rpc_client + * + * @{ + **/ - return r_o.status; +/********************************************************************** + Initialize a new spoolss buff for use by a client rpc +**********************************************************************/ +static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx) +{ + buffer->ptr = (size != 0); + buffer->size = size; + buffer->string_at_end = size; + prs_init(&buffer->prs, size, ctx, MARSHALL); + buffer->struct_start = prs_offset(&buffer->prs); } -/**************************************************************************** -do a SPOOLSS Enum Printers -****************************************************************************/ -uint32 spoolss_enum_printers(uint32 flags, fstring srv_name, uint32 level, - NEW_BUFFER *buffer, uint32 offered, - uint32 *needed, uint32 *returned) +/********************************************************************* + Decode various spoolss rpc's and info levels + ********************************************************************/ + +/********************************************************************** +**********************************************************************/ +static void decode_printer_info_0(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, + uint32 returned, PRINTER_INFO_0 **info) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_ENUMPRINTERS q_o; - SPOOL_R_ENUMPRINTERS r_o; - TALLOC_CTX *ctx = prs_get_mem_context(&buffer->prs); + uint32 i; + PRINTER_INFO_0 *inf; - struct cli_connection *con = NULL; + inf=(PRINTER_INFO_0 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_0)); - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return False; + buffer->prs.data_offset=0; - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); + for (i=0; iprs.data_offset=0; - prs_switch_type(&buffer->prs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; + for (i=0; iprs.data_offset=0; - cli_connection_unlink(con); + for (i=0; iprs); + uint32 i; + PRINTER_INFO_3 *inf; + + inf=(PRINTER_INFO_3 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_3)); + + buffer->prs.data_offset=0; - struct cli_connection *con = NULL; + for (i=0; iprs, 0); - DEBUG(5,("SPOOLSS Enum Ports (Server: %s level: %d)\n", srv_name, level)); + for (i=0; iprs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; + inf=(PORT_INFO_2*)talloc(mem_ctx, returned*sizeof(PORT_INFO_2)); - if(new_spoolss_io_r_enumports("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_ENUMPORTS: %s\n", nt_errstr(r_o.status))); - } - - *needed=r_o.needed; - *returned=r_o.returned; - } + prs_set_offset(&buffer->prs, 0); + + for (i=0; iprs.data_offset=0; - cli_connection_unlink(con); + for (i=0; iprs); + uint32 i; + DRIVER_INFO_2 *inf; + + inf=(DRIVER_INFO_2 *)talloc(mem_ctx, returned*sizeof(DRIVER_INFO_2)); - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + buffer->prs.data_offset=0; - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); + for (i=0; iprs.data_offset=0; - /* turn parameters into data stream */ - if (spoolss_io_q_enumjobs("", &q_o, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_ENUMJOBS, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - prs_mem_free(&buf ); + for (i=0; iprs, 0); - return r_o.status; + smb_io_driverdir_1("", buffer, inf, 0); + + *info=inf; } -/*************************************************************************** -do a SPOOLSS Enum printer datas -****************************************************************************/ -uint32 spoolss_enum_printerdata(const POLICY_HND *hnd, uint32 idx, - uint32 *valuelen, uint16 *value, uint32 *rvaluelen, - uint32 *type, uint32 *datalen, uint8 *data, - uint32 *rdatalen) +/** Return a handle to the specified printer or print server. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param printername The name of the printer or print server to be + * opened in UNC format. + * + * @param datatype Specifies the default data type for the printer. + * + * @param access_required The access rights requested on the printer or + * print server. + * + * @param station The UNC name of the requesting workstation. + * + * @param username The name of the user requesting the open. + * + * @param pol Returned policy handle. + */ + +/********************************************************************************* + Win32 API - OpenPrinter() + ********************************************************************************/ + +WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *printername, char *datatype, uint32 access_required, + char *station, char *username, POLICY_HND *pol) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_ENUMPRINTERDATA q_o; - SPOOL_R_ENUMPRINTERDATA r_o; - TALLOC_CTX *mem_ctx = NULL; - - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + prs_struct qbuf, rbuf; + SPOOL_Q_OPEN_PRINTER_EX q; + SPOOL_R_OPEN_PRINTER_EX r; + WERROR result = W_ERROR(ERRgeneral); - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); - return False; - } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SPOOLSS_ENUMPRINTERDATA*/ - - DEBUG(4,("SPOOLSS Enum Printer data\n")); - - make_spoolss_q_enumprinterdata(&q_o, hnd, idx, *valuelen, *datalen); - - /* turn parameters into data stream */ - if (spoolss_io_q_enumprinterdata("", &q_o, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_ENUMPRINTERDATA, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - prs_mem_free(&buf ); - - r_o.data=data; - r_o.value=value; - - if(spoolss_io_r_enumprinterdata("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_ENUMPRINTERDATA: %s\n", nt_errstr(r_o.status))); - } - - *valuelen=r_o.valuesize; - *rvaluelen=r_o.realvaluesize; - *type=r_o.type; - *datalen=r_o.datasize; - *rdatalen=r_o.realdatasize; + 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 */ + + make_spoolss_q_open_printer_ex(&q, printername, datatype, + access_required, station, username); + + /* Marshall data and send request */ + + if (!spoolss_io_q_open_printer_ex("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_OPENPRINTEREX, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_open_printer_ex("", &r, &rbuf, 0)) + goto done; - prs_mem_free(&rbuf); - prs_mem_free(&buf ); - if (mem_ctx) - talloc_destroy(mem_ctx); + /* Return output parameters */ - return r_o.status; + result = r.status; + + if (W_ERROR_IS_OK(result)) + *pol = r.handle; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/**************************************************************************** -do a SPOOLSS Enum printer datas -****************************************************************************/ -uint32 spoolss_getprinter(const POLICY_HND *hnd, uint32 level, - NEW_BUFFER *buffer, uint32 offered, - uint32 *needed) +/** Close a printer handle + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param pol Policy handle of printer or print server to close. + */ +/********************************************************************************* + Win32 API - ClosePrinter() + ********************************************************************************/ + +WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_GETPRINTER q_o; - SPOOL_R_GETPRINTER r_o; - TALLOC_CTX *ctx = prs_get_mem_context(&buffer->prs); + prs_struct qbuf, rbuf; + SPOOL_Q_CLOSEPRINTER q; + SPOOL_R_CLOSEPRINTER r; + WERROR result = W_ERROR(ERRgeneral); - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); + /* Initialise parse structures */ - /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(5,("SPOOLSS Enum Printer data)\n")); + /* Initialise input parameters */ - make_spoolss_q_getprinter(&q_o, hnd, level, buffer, offered); + make_spoolss_q_closeprinter(&q, pol); - /* turn parameters into data stream */ - if (spoolss_io_q_getprinter("", &q_o, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTER, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - prs_mem_free(&buf ); + /* Marshall data and send request */ - prs_switch_type(&buffer->prs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; + if (!spoolss_io_q_closeprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_CLOSEPRINTER, &qbuf, &rbuf)) + goto done; - if(!spoolss_io_r_getprinter("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_GETPRINTER: %s\n", nt_errstr(r_o.status))); - } - *needed=r_o.needed; - } - } + /* Unmarshall response */ + + if (!spoolss_io_r_closeprinter("", &r, &rbuf, 0)) + goto done; - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + /* Return output parameters */ + + result = r.status; + + if (W_ERROR_IS_OK(result)) + *pol = r.handle; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return r_o.status; + return result; } -/**************************************************************************** -do a SPOOLSS Enum printer driver -****************************************************************************/ -uint32 spoolss_getprinterdriver(const POLICY_HND *hnd, - const char *environment, uint32 level, - NEW_BUFFER *buffer, uint32 offered, - uint32 *needed) +/** Enumerate printers on a print server. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param offered Buffer size offered in the request. + * @param needed Number of bytes needed to complete the request. + * may be NULL. + * + * @param flags Selected from PRINTER_ENUM_* flags. + * @param level Request information level. + * + * @param num_printers Pointer to number of printers returned. May be + * NULL. + * @param ctr Return structure for printer information. May + * be NULL. + */ +/********************************************************************************* + Win32 API - EnumPrinters() + ********************************************************************************/ + +WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + uint32 flags, uint32 level, + uint32 *num_printers, PRINTER_INFO_CTR *ctr) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_GETPRINTERDRIVER2 q_o; - SPOOL_R_GETPRINTERDRIVER2 r_o; - TALLOC_CTX *ctx = prs_get_mem_context(&buffer->prs); + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMPRINTERS q; + SPOOL_R_ENUMPRINTERS r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); + + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_enumprinters(&q, flags, server, level, &buffer, + offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_enumprinters("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERS, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (spoolss_io_r_enumprinters("", &r, &rbuf, 0)) { + if (needed) + *needed = r.needed; + } + + result = r.status; + + /* Return output parameters */ + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + if (num_printers) + *num_printers = r.returned; + + if (!ctr) + goto done; + + switch (level) { + case 0: + decode_printer_info_0(mem_ctx, r.buffer, r.returned, + &ctr->printers_0); + break; + case 1: + decode_printer_info_1(mem_ctx, r.buffer, r.returned, + &ctr->printers_1); + break; + case 2: + decode_printer_info_2(mem_ctx, r.buffer, r.returned, + &ctr->printers_2); + break; + case 3: + decode_printer_info_3(mem_ctx, r.buffer, r.returned, + &ctr->printers_3); + break; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + return result; +} - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); +/********************************************************************************* + Win32 API - EnumPorts() + ********************************************************************************/ +/** Enumerate printer ports on a print server. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param offered Buffer size offered in the request. + * @param needed Number of bytes needed to complete the request. + * May be NULL. + * + * @param level Requested information level. + * + * @param num_ports Pointer to number of ports returned. May be NULL. + * @param ctr Pointer to structure holding port information. + * May be NULL. + */ - /* create and send a MSRPC command with api SPOOLSS_ENUMJOBS */ +WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + uint32 level, int *num_ports, PORT_INFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMPORTS q; + SPOOL_R_ENUMPORTS r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + fstring server; - DEBUG(5,("SPOOLSS Enum Printer driver)\n")); + ZERO_STRUCT(q); + ZERO_STRUCT(r); - make_spoolss_q_getprinterdriver2(&q_o, hnd, environment, level, 2, 0, buffer, offered); + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); - /* turn parameters into data stream */ - if (spoolss_io_q_getprinterdriver2("", &q_o, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTERDRIVER2, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - prs_mem_free(&buf ); + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_enumports(&q, server, level, &buffer, offered); + + /* Marshall data and send request */ - prs_switch_type(&buffer->prs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; + if (!spoolss_io_q_enumports("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENUMPORTS, &qbuf, &rbuf)) + goto done; - if(spoolss_io_r_getprinterdriver2("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_GETPRINTERDRIVER2: %s\n", nt_errstr(r_o.status))); - } + /* Unmarshall response */ - *needed=r_o.needed; - } + if (spoolss_io_r_enumports("", &r, &rbuf, 0)) { + if (needed) + *needed = r.needed; } + + result = r.status; - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + /* Return output parameters */ - return r_o.status; -} + if (!W_ERROR_IS_OK(result)) + goto done; + + if (num_ports) + *num_ports = r.returned; + if (!ctr) + goto done; + + switch (level) { + case 1: + decode_port_info_1(mem_ctx, r.buffer, r.returned, + &ctr->port.info_1); + break; + case 2: + decode_port_info_2(mem_ctx, r.buffer, r.returned, + &ctr->port.info_2); + break; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} +/********************************************************************************* + Win32 API - GetPrinter() + ********************************************************************************/ -/**************************************************************************** -do a SPOOLSS Open Printer Ex -****************************************************************************/ -BOOL spoolss_open_printer_ex( const char *printername, - const char *datatype, uint32 access_required, - const char *station, const char *username, - POLICY_HND *hnd) +WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *pol, uint32 level, + PRINTER_INFO_CTR *ctr) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_OPEN_PRINTER_EX q_o; - BOOL valid_pol = False; - fstring srv_name; - char *s = NULL; - struct cli_connection *con = NULL; - TALLOC_CTX *mem_ctx = NULL; + prs_struct qbuf, rbuf; + SPOOL_Q_GETPRINTER q; + SPOOL_R_GETPRINTER r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_getprinter(mem_ctx, &q, pol, level, &buffer, offered); - memset(srv_name, 0, sizeof(srv_name)); - fstrcpy(srv_name, printername); + /* Marshall data and send request */ - s = strchr_m(&srv_name[2], '\\'); - if (s != NULL) - *s = '\0'; + if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTER, &qbuf, &rbuf)) + goto done; - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return False; + /* Unmarshall response */ - if (hnd == NULL) - return False; + if (!spoolss_io_r_getprinter("", &r, &rbuf, 0)) + goto done; - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); - return False; + if (needed) + *needed = r.needed; + + /* Return output parameters */ + + result = r.status; + + if (W_ERROR_IS_OK(result)) { + switch (level) { + case 0: + decode_printer_info_0(mem_ctx, r.buffer, 1, &ctr->printers_0); + break; + case 1: + decode_printer_info_1(mem_ctx, r.buffer, 1, &ctr->printers_1); + break; + case 2: + decode_printer_info_2(mem_ctx, r.buffer, 1, &ctr->printers_2); + break; + case 3: + decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3); + break; + } } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - /* create and send a MSRPC command with api SPOOLSS_OPENPRINTEREX */ + return result; +} + +/********************************************************************************* + Win32 API - SetPrinter() + ********************************************************************************/ +/** Set printer info + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param pol Policy handle on printer to set info. + * @param level Information level to set. + * @param ctr Pointer to structure holding printer information. + * @param command Specifies the action performed. See + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_13ua.asp + * for details. + * + */ - DEBUG(5,("SPOOLSS Open Printer Ex\n")); +WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 level, + PRINTER_INFO_CTR *ctr, uint32 command) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_SETPRINTER q; + SPOOL_R_SETPRINTER r; + WERROR result = W_ERROR(ERRgeneral); - make_spoolss_q_open_printer_ex(&q_o, printername, datatype, - access_required, station, username); + ZERO_STRUCT(q); + ZERO_STRUCT(r); - /* turn parameters into data stream */ - if (spoolss_io_q_open_printer_ex("", &q_o, &buf, 0) && - rpc_con_pipe_req(con, SPOOLSS_OPENPRINTEREX, &buf, &rbuf)) - { - SPOOL_R_OPEN_PRINTER_EX r_o; - BOOL p = True; + /* Initialise input parameters */ - spoolss_io_r_open_printer_ex("", &r_o, &rbuf, 0); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command); - if (prs_offset(&rbuf)!= 0 && r_o.status != 0) - { - /* report error code */ - DEBUG(3,("SPOOLSS_OPENPRINTEREX: %s\n", nt_errstr(r_o.status))); - p = False; - } + /* Marshall data and send request */ - if (p) - { - /* ok, at last: we're happy. return the policy handle */ - *hnd = r_o.handle; + if (!spoolss_io_q_setprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTER, &qbuf, &rbuf)) + goto done; - /* associate the handle returned with the current - state of the clienjt connection */ - valid_pol = RpcHndList_set_connection(hnd, con); + /* Unmarshall response */ - } - } + if (!spoolss_io_r_setprinter("", &r, &rbuf, 0)) + goto done; + + result = r.status; +done: + prs_mem_free(&qbuf); prs_mem_free(&rbuf); - prs_mem_free(&buf ); - if (mem_ctx) - talloc_destroy(mem_ctx); - return valid_pol; + return result; } -/**************************************************************************** - do a SPOOLSS AddPrinterEx() - **ALWAYS** uses as PRINTER_INFO level 2 struct -****************************************************************************/ -BOOL spoolss_addprinterex(POLICY_HND *hnd, const char* srv_name, PRINTER_INFO_2 *info2) +/********************************************************************************* + Win32 API - GetPrinterDriver() + ********************************************************************************/ +/** Get installed printer drivers for a given printer + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param offered Buffer size offered in the request. + * @param needed Number of bytes needed to complete the request. + * may be NULL. + * + * @param pol Pointer to an open policy handle for the printer + * opened with cli_spoolss_open_printer_ex(). + * @param level Requested information level. + * @param env The print environment or archictecture. This is + * "Windows NT x86" for NT4. + * @param ctr Returned printer driver information. + */ + +WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *pol, uint32 level, + char *env, PRINTER_DRIVER_CTR *ctr) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_ADDPRINTEREX q_o; - SPOOL_R_ADDPRINTEREX r_o; - struct cli_connection *con = NULL; - TALLOC_CTX *mem_ctx = NULL; - fstring the_client_name; - BOOL valid_pol = True; + prs_struct qbuf, rbuf; + SPOOL_Q_GETPRINTERDRIVER2 q; + SPOOL_R_GETPRINTERDRIVER2 r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + fstrcpy (server, cli->desthost); + strupper (server); + + /* Initialise input parameters */ + init_buffer(&buffer, offered, mem_ctx); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return NT_STATUS_ACCESS_DENIED; + make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2, + &buffer, offered); - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + /* Marshall data and send request */ - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("spoolss_addprinterex: talloc_init() failed!\n")); - return NT_STATUS_ACCESS_DENIED; + if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0)) { + if (needed) + *needed = r.needed; + } + + result = r.status; + + /* Return output parameters */ + + if (!W_ERROR_IS_OK(result)) + goto done; + + if (!ctr) + goto done; + + switch (level) { + case 1: + decode_printer_driver_1(mem_ctx, r.buffer, 1, &ctr->info1); + break; + case 2: + decode_printer_driver_2(mem_ctx, r.buffer, 1, &ctr->info2); + break; + case 3: + decode_printer_driver_3(mem_ctx, r.buffer, 1, &ctr->info3); + break; } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* create and send a MSRPC command with api SPOOLSS_ENUMPORTS */ - DEBUG(5,("SPOOLSS Add Printer Ex (Server: %s)\n", srv_name)); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/********************************************************************************* + Win32 API - EnumPrinterDrivers() + ********************************************************************************/ +/********************************************************************** + * Get installed printer drivers for a given printer + */ +WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + uint32 level, char *env, + uint32 *num_drivers, + PRINTER_DRIVER_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMPRINTERDRIVERS q; + SPOOL_R_ENUMPRINTERDRIVERS r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); + + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Write the request */ + + make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, + offered); - fstrcpy(the_client_name, "\\\\"); - fstrcat(the_client_name, con->pCli_state->desthost); - strupper(the_client_name); + /* Marshall data and send request */ + if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf)) + goto done; - make_spoolss_q_addprinterex(mem_ctx, &q_o, srv_name, the_client_name, - /* "Administrator", */ - con->pCli_state->user_name, - 2, info2); - - /* turn parameters into data stream and send the request */ - if (spoolss_io_q_addprinterex("", &q_o, &buf, 0) && - rpc_con_pipe_req(con, SPOOLSS_ADDPRINTEREX, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - - if(spoolss_io_r_addprinterex("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - /* report error code */ - DEBUG(3,("SPOOLSS_ADDPRINTEREX: %s\n", nt_errstr(r_o.status))); - valid_pol = False; - } - } - - if (valid_pol) - { - /* ok, at last: we're happy. return the policy handle */ - copy_policy_hnd( hnd, &r_o.handle); - - /* associate the handle returned with the current - state of the clienjt connection */ - RpcHndList_set_connection(hnd, con); + /* Unmarshall response */ + + if (!spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0)) + goto done; + + if (needed) + *needed = r.needed; + + if (num_drivers) + *num_drivers = r.returned; + + result = r.status; + + /* Return output parameters */ + + if (W_ERROR_IS_OK(result) && (r.returned != 0)) { + *num_drivers = r.returned; + + switch (level) { + case 1: + decode_printer_driver_1(mem_ctx, r.buffer, r.returned, &ctr->info1); + break; + case 2: + decode_printer_driver_2(mem_ctx, r.buffer, r.returned, &ctr->info2); + break; + case 3: + decode_printer_driver_3(mem_ctx, r.buffer, r.returned, &ctr->info3); + break; } - } + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + + +/********************************************************************************* + Win32 API - GetPrinterDriverDirectory() + ********************************************************************************/ +/********************************************************************** + * Get installed printer drivers for a given printer + */ +WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + uint32 level, char *env, + DRIVER_DIRECTORY_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_GETPRINTERDRIVERDIR q; + SPOOL_R_GETPRINTERDRIVERDIR r; + NEW_BUFFER buffer; + WERROR result = W_ERROR(ERRgeneral); + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); + + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Write the request */ + + make_spoolss_q_getprinterdriverdir(&q, server, env, level, &buffer, + offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_getprinterdriverdir ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVERDIRECTORY, + &qbuf, &rbuf)) + goto done; + /* Unmarshall response */ - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + if (spoolss_io_r_getprinterdriverdir ("", &r, &rbuf, 0)) { + if (needed) + *needed = r.needed; + } + + /* Return output parameters */ - if (mem_ctx) - talloc_destroy(mem_ctx); + result = r.status; + + if (W_ERROR_IS_OK(result)) { + switch (level) { + case 1: + decode_printerdriverdir_1(mem_ctx, r.buffer, 1, + &ctr->info1); + break; + } + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return valid_pol; + return result; } -/**************************************************************************** -do a SPOOL Close -****************************************************************************/ -BOOL spoolss_closeprinter(POLICY_HND *hnd) +/********************************************************************************* + Win32 API - AddPrinterDriver() + ********************************************************************************/ +/********************************************************************** + * Install a printer driver + */ +WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint32 level, + PRINTER_DRIVER_CTR *ctr) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_CLOSEPRINTER q_c; - BOOL valid_close = False; - TALLOC_CTX *mem_ctx = NULL; + prs_struct qbuf, rbuf; + SPOOL_Q_ADDPRINTERDRIVER q; + SPOOL_R_ADDPRINTERDRIVER r; + WERROR result = W_ERROR(ERRgeneral); + fstring server; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); - if (hnd == NULL) - return False; - - /* create and send a MSRPC command with api SPOOLSS_CLOSEPRINTER */ - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); - return False; - } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); - DEBUG(4,("SPOOL Close Printer\n")); + /* Initialise input parameters */ - /* store the parameters */ - make_spoolss_q_closeprinter(&q_c, hnd); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* turn parameters into data stream */ - if (spoolss_io_q_closeprinter("", &q_c, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_CLOSEPRINTER, &buf, &rbuf)) - { - SPOOL_R_CLOSEPRINTER r_c; + /* Write the request */ - spoolss_io_r_closeprinter("", &r_c, &rbuf, 0); + make_spoolss_q_addprinterdriver (mem_ctx, &q, server, level, ctr); - if (prs_offset(&rbuf)!=0 && r_c.status != 0) - { - /* report error code */ - DEBUG(3,("SPOOL_CLOSEPRINTER: %s\n", nt_errstr(r_c.status))); - } - else - valid_close = True; - } + /* Marshall data and send request */ - prs_mem_free(&rbuf); - prs_mem_free(&buf ); - if (mem_ctx) - talloc_destroy(mem_ctx); + if (!spoolss_io_q_addprinterdriver ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTERDRIVER, &qbuf, &rbuf)) + goto done; - /* disassociate with the cli_connection */ - RpcHndList_del_connection(hnd); + /* Unmarshall response */ - return valid_close; + if (!spoolss_io_r_addprinterdriver ("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/**************************************************************************** -do a SPOOLSS Get printer datas -****************************************************************************/ -uint32 spoolss_getprinterdata(const POLICY_HND *hnd, const UNISTR2 *valuename, - uint32 in_size, - uint32 *type, - uint32 *out_size, - uint8 *data, - uint32 *needed) +/********************************************************************************* + Win32 API - AddPrinter() + ********************************************************************************/ +/********************************************************************** + * Install a printer + */ +WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 level, PRINTER_INFO_CTR*ctr) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_GETPRINTERDATA q_o; - SPOOL_R_GETPRINTERDATA r_o; - TALLOC_CTX *mem_ctx = NULL; + prs_struct qbuf, rbuf; + SPOOL_Q_ADDPRINTEREX q; + SPOOL_R_ADDPRINTEREX r; + WERROR result = W_ERROR(ERRgeneral); + fstring server, + client, + user; - if (hnd == NULL) - return NT_STATUS_INVALID_PARAMETER; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); - return False; - } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + slprintf (client, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (client); + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); + fstrcpy (user, cli->user_name); + + /* Initialise input parameters */ - /* create and send a MSRPC command with api SPOOLSS_GETPRINTERDATA */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(5,("SPOOLSS Get Printer data)\n")); + /* Write the request */ - make_spoolss_q_getprinterdata(&q_o, hnd,(UNISTR2 *)valuename, in_size); + make_spoolss_q_addprinterex (mem_ctx, &q, server, client, user, + level, ctr); - /* turn parameters into data stream */ - if (spoolss_io_q_getprinterdata("", &q_o, &buf, 0) && - rpc_hnd_pipe_req(hnd, SPOOLSS_GETPRINTERDATA, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - prs_mem_free(&buf ); + /* Marshall data and send request */ - r_o.data=data; + if (!spoolss_io_q_addprinterex ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTEREX, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ - if(spoolss_io_r_getprinterdata("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_GETPRINTERDATA: %s\n", nt_errstr(r_o.status))); - } + if (!spoolss_io_r_addprinterex ("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ - *type=r_o.type; - *out_size=r_o.size; - *needed=r_o.needed; - } - } + result = r.status; - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return r_o.status; + return result; } -/**************************************************************************** -do a SPOOLSS Get Printer Driver Direcotry -****************************************************************************/ -uint32 spoolss_getprinterdriverdir(fstring srv_name, fstring env_name, uint32 level, - NEW_BUFFER *buffer, uint32 offered, - uint32 *needed) +/********************************************************************************* + Win32 API - DeltePrinterDriver() + ********************************************************************************/ +/********************************************************************** + * Delete a Printer Driver from the server (does not remove + * the driver files + */ +WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, + TALLOC_CTX *mem_ctx, char *arch, + char *driver) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_GETPRINTERDRIVERDIR q_o; - SPOOL_R_GETPRINTERDRIVERDIR r_o; - TALLOC_CTX *ctx = prs_get_mem_context(&buffer->prs); + prs_struct qbuf, rbuf; + SPOOL_Q_DELETEPRINTERDRIVER q; + SPOOL_R_DELETEPRINTERDRIVER r; + WERROR result = W_ERROR(ERRgeneral); + fstring server; - struct cli_connection *con = NULL; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return False; - prs_init(&buf, MAX_PDU_FRAG_LEN, ctx, MARSHALL); - prs_init(&rbuf, 0, ctx, UNMARSHALL); + /* Initialise input parameters */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* create and send a MSRPC command with api SPOOLSS_ENUM_PRINTERS */ + slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper (server); - DEBUG(5,("SPOOLSS GetPrinterDriverDir (Server: %s Env: %s level: %d)\n", - srv_name, env_name, level)); + /* Write the request */ - make_spoolss_q_getprinterdriverdir(&q_o, srv_name, env_name, level, - buffer, offered); + make_spoolss_q_deleteprinterdriver(mem_ctx, &q, server, arch, driver); - /* turn parameters into data stream */ - if (spoolss_io_q_getprinterdriverdir("", &q_o, &buf, 0) && - rpc_con_pipe_req(con, SPOOLSS_GETPRINTERDRIVERDIRECTORY, &buf, &rbuf)) - { - prs_mem_free(&buf ); - ZERO_STRUCT(r_o); + /* Marshall data and send request */ - prs_switch_type(&buffer->prs, UNMARSHALL); - prs_set_offset(&buffer->prs, 0); - r_o.buffer=buffer; + if (!spoolss_io_q_deleteprinterdriver ("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli,SPOOLSS_DELETEPRINTERDRIVER , &qbuf, &rbuf)) + goto done; - if(spoolss_io_r_getprinterdriverdir("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - DEBUG(3,("SPOOLSS_GETPRINTERDRIVERDIRECTORY: %s\n", nt_errstr(r_o.status))); - } + /* Unmarshall response */ - *needed=r_o.needed; - } - } + if (!spoolss_io_r_deleteprinterdriver ("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + result = r.status; - cli_connection_unlink(con); + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - return r_o.status; + return result; } -/****************************************************************************** - AddPrinterDriver() - *****************************************************************************/ -uint32 spoolss_addprinterdriver(const char *srv_name, uint32 level, PRINTER_DRIVER_CTR *info) +/********************************************************************************* + Win32 API - GetPrinterProcessorDirectory() + ********************************************************************************/ + +WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + char *name, char *environment, + fstring procdir) { - prs_struct rbuf; - prs_struct buf; - SPOOL_Q_ADDPRINTERDRIVER q_o; - SPOOL_R_ADDPRINTERDRIVER r_o; - TALLOC_CTX *mem_ctx = NULL; - struct cli_connection *con = NULL; - - if (!cli_connection_init(srv_name, PIPE_SPOOLSS, &con)) - return False; + prs_struct qbuf, rbuf; + SPOOL_Q_GETPRINTPROCESSORDIRECTORY q; + SPOOL_R_GETPRINTPROCESSORDIRECTORY r; + int level = 1; + WERROR result = W_ERROR(ERRgeneral); + NEW_BUFFER buffer; - if ((mem_ctx=talloc_init()) == NULL) - { - DEBUG(0,("msrpc_spoolss_enum_jobs: talloc_init failed!\n")); - return False; - } - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* make the ADDPRINTERDRIVER PDU */ - make_spoolss_q_addprinterdriver(mem_ctx, &q_o, srv_name, level, info); - - /* turn the data into an io stream */ - if (spoolss_io_q_addprinterdriver("", &q_o, &buf, 0) && - rpc_con_pipe_req(con, SPOOLSS_ADDPRINTERDRIVER, &buf, &rbuf)) - { - ZERO_STRUCT(r_o); - - if(spoolss_io_r_addprinterdriver("", &r_o, &rbuf, 0)) - { - if (r_o.status != NT_STATUS_OK) - { - /* report error code */ - DEBUG(3,("SPOOLSS_ADDPRINTERDRIVER: %s\n", nt_errstr(r_o.status))); - } - } - } + ZERO_STRUCT(q); + ZERO_STRUCT(r); + /* Initialise parse structures */ - prs_mem_free(&rbuf); - prs_mem_free(&buf ); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if (mem_ctx) - talloc_destroy(mem_ctx); + /* Initialise input parameters */ + + init_buffer(&buffer, offered, mem_ctx); + + make_spoolss_q_getprintprocessordirectory( + &q, name, environment, level, &buffer, offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_getprintprocessordirectory("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTPROCESSORDIRECTORY, + &qbuf, &rbuf)) + goto done; - return r_o.status; + /* Unmarshall response */ + + if (!spoolss_io_r_getprintprocessordirectory("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (needed) + *needed = r.needed; + if (W_ERROR_IS_OK(result)) + fstrcpy(procdir, "Not implemented!"); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } + +/** Add a form to a printer. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param handle Policy handle opened with cli_spoolss_open_printer_ex + * or cli_spoolss_addprinterex. + * @param level Form info level to add - should always be 1. + * @param form A pointer to the form to be added. + * + */ + +WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *handle, uint32 level, FORM *form) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ADDFORM q; + SPOOL_R_ADDFORM r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_addform(&q, handle, level, form); + + /* Marshall data and send request */ + + if (!spoolss_io_q_addform("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ADDFORM, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_addform("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/** Set a form on a printer. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param handle Policy handle opened with cli_spoolss_open_printer_ex + * or cli_spoolss_addprinterex. + * @param level Form info level to set - should always be 1. + * @param form A pointer to the form to be set. + * + */ + +WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *handle, uint32 level, char *form_name, + FORM *form) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_SETFORM q; + SPOOL_R_SETFORM r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_setform(&q, handle, level, form_name, form); + + /* Marshall data and send request */ + + if (!spoolss_io_q_setform("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_SETFORM, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_setform("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (!W_ERROR_IS_OK(result)) + goto done; + + + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/** Get a form on a printer. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param handle Policy handle opened with cli_spoolss_open_printer_ex + * or cli_spoolss_addprinterex. + * @param formname Name of the form to get + * @param level Form info level to get - should always be 1. + * + */ + +WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *handle, char *formname, uint32 level, + FORM_1 *form) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_GETFORM q; + SPOOL_R_GETFORM r; + WERROR result = W_ERROR(ERRgeneral); + NEW_BUFFER buffer; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + make_spoolss_q_getform(&q, handle, formname, level, &buffer, offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_getform("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_GETFORM, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_getform("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (needed) + *needed = r.needed; + + if (W_ERROR_IS_OK(result)) + smb_io_form_1("", r.buffer, form, 0); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/** Delete a form on a printer. + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param handle Policy handle opened with cli_spoolss_open_printer_ex + * or cli_spoolss_addprinterex. + * @param form The name of the form to delete. + * + */ + +WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *handle, char *form_name) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_DELETEFORM q; + SPOOL_R_DELETEFORM r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_deleteform(&q, handle, form_name); + + /* Marshall data and send request */ + + if (!spoolss_io_q_deleteform("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_DELETEFORM, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_deleteform("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +static void decode_forms_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, + uint32 num_forms, FORM_1 **forms) +{ + int i; + + *forms = (FORM_1 *)talloc(mem_ctx, num_forms * sizeof(FORM_1)); + buffer->prs.data_offset = 0; + + for (i = 0; i < num_forms; i++) + smb_io_form_1("", buffer, &((*forms)[i]), 0); +} + +/** Enumerate forms + * + * @param cli Pointer to client state structure which is open + * on the SPOOLSS pipe. + * @param mem_ctx Pointer to an initialised talloc context. + * + * @param offered Buffer size offered in the request. + * @param needed Number of bytes needed to complete the request. + * may be NULL. + * or cli_spoolss_addprinterex. + * @param level Form info level to get - should always be 1. + * @param handle Open policy handle + * + */ + +WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *handle, int level, uint32 *num_forms, + FORM_1 **forms) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMFORMS q; + SPOOL_R_ENUMFORMS r; + WERROR result = W_ERROR(ERRgeneral); + NEW_BUFFER buffer; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + make_spoolss_q_enumforms(&q, handle, level, &buffer, offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_enumforms("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENUMFORMS, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_enumforms("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (needed) + *needed = r.needed; + + if (num_forms) + *num_forms = r.numofforms; + + decode_forms_1(mem_ctx, r.buffer, *num_forms, forms); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +static void decode_jobs_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, + uint32 num_jobs, JOB_INFO_1 **jobs) +{ + uint32 i; + + *jobs = (JOB_INFO_1 *)talloc(mem_ctx, num_jobs * sizeof(JOB_INFO_1)); + buffer->prs.data_offset = 0; + + for (i = 0; i < num_jobs; i++) + smb_io_job_info_1("", buffer, &((*jobs)[i]), 0); +} + +static void decode_jobs_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, + uint32 num_jobs, JOB_INFO_2 **jobs) +{ + uint32 i; + + *jobs = (JOB_INFO_2 *)talloc(mem_ctx, num_jobs * sizeof(JOB_INFO_2)); + buffer->prs.data_offset = 0; + + for (i = 0; i < num_jobs; i++) + smb_io_job_info_2("", buffer, &((*jobs)[i]), 0); +} + +/* Enumerate jobs */ + +WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *hnd, uint32 level, uint32 firstjob, + uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMJOBS q; + SPOOL_R_ENUMJOBS r; + WERROR result = W_ERROR(ERRgeneral); + NEW_BUFFER buffer; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + make_spoolss_q_enumjobs(&q, hnd, firstjob, num_jobs, level, &buffer, + offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_enumjobs("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENUMJOBS, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_enumjobs("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (needed) + *needed = r.needed; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + *returned = r.returned; + + switch(level) { + case 1: + decode_jobs_1(mem_ctx, r.buffer, r.returned, + ctr->job.job_info_1); + break; + case 2: + decode_jobs_2(mem_ctx, r.buffer, r.returned, + ctr->job.job_info_2); + break; + default: + DEBUG(3, ("unsupported info level %d", level)); + break; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Set job */ + +WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 jobid, uint32 level, + uint32 command) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_SETJOB q; + SPOOL_R_SETJOB r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_setjob(&q, hnd, jobid, level, command); + + /* Marshall data and send request */ + + if (!spoolss_io_q_setjob("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_SETJOB, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_setjob("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Get job */ + +WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *hnd, uint32 jobid, uint32 level, + JOB_INFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_GETJOB q; + SPOOL_R_GETJOB r; + WERROR result = W_ERROR(ERRgeneral); + NEW_BUFFER buffer; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + init_buffer(&buffer, offered, mem_ctx); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + make_spoolss_q_getjob(&q, hnd, jobid, level, &buffer, offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_getjob("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_GETJOB, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_getjob("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (needed) + *needed = r.needed; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + switch(level) { + case 1: + decode_jobs_1(mem_ctx, r.buffer, 1, ctr->job.job_info_1); + break; + case 2: + decode_jobs_2(mem_ctx, r.buffer, 1, ctr->job.job_info_2); + break; + default: + DEBUG(3, ("unsupported info level %d", level)); + break; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Startpageprinter. Sent to notify the spooler when a page is about to be + sent to a printer. */ + +WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_STARTPAGEPRINTER q; + SPOOL_R_STARTPAGEPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_startpageprinter(&q, hnd); + + /* Marshall data and send request */ + + if (!spoolss_io_q_startpageprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_STARTPAGEPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_startpageprinter("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Endpageprinter. Sent to notify the spooler when a page has finished + being sent to a printer. */ + +WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENDPAGEPRINTER q; + SPOOL_R_ENDPAGEPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_endpageprinter(&q, hnd); + + /* Marshall data and send request */ + + if (!spoolss_io_q_endpageprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENDPAGEPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_endpageprinter("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Startdocprinter. Sent to notify the spooler that a document is about + to be spooled for printing. */ + +WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *docname, + char *outputfile, char *datatype, + uint32 *jobid) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_STARTDOCPRINTER q; + SPOOL_R_STARTDOCPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + uint32 level = 1; + + 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 */ + + make_spoolss_q_startdocprinter(&q, hnd, level, docname, outputfile, + datatype); + + /* Marshall data and send request */ + + if (!spoolss_io_q_startdocprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_STARTDOCPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_startdocprinter("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + if (W_ERROR_IS_OK(result)) + *jobid = r.jobid; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Enddocprinter. Sent to notify the spooler that a document has finished + being spooled. */ + +WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENDDOCPRINTER q; + SPOOL_R_ENDDOCPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_enddocprinter(&q, hnd); + + /* Marshall data and send request */ + + if (!spoolss_io_q_enddocprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENDDOCPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_enddocprinter("", &r, &rbuf, 0)) + goto done; + + /* Return output parameters */ + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Get printer data */ + +WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 offered, uint32 *needed, + POLICY_HND *hnd, char *valuename, + uint32 *data_type, char **data, + uint32 *data_size) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_GETPRINTERDATA q; + SPOOL_R_GETPRINTERDATA r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_getprinterdata(&q, hnd, valuename, offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_getprinterdata("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTERDATA, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_getprinterdata("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (needed) + *needed = r.needed; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + /* Return output parameters */ + + if (data_type) + *data_type = r.type; + + if (data) { + *data = (char *)talloc(mem_ctx, r.needed); + memcpy(*data, r.data, r.needed); + } + + if (data_size) + *data_size = r.needed; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Set printer data */ + +WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *value, + uint32 data_type, char *data, + uint32 data_size) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_SETPRINTERDATA q; + SPOOL_R_SETPRINTERDATA r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_setprinterdata(&q, hnd, value, data, data_size); + + /* Marshall data and send request */ + + if (!spoolss_io_q_setprinterdata("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTERDATA, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_setprinterdata("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Enum printer data */ + +WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 ndx, + uint32 value_offered, uint32 data_offered, + uint32 *value_needed, uint32 *data_needed, + char **value, uint32 *data_type, char **data, + uint32 *data_size) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_ENUMPRINTERDATA q; + SPOOL_R_ENUMPRINTERDATA r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_enumprinterdata(&q, hnd, ndx, value_offered, data_offered); + + /* Marshall data and send request */ + + if (!spoolss_io_q_enumprinterdata("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERDATA, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_enumprinterdata("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + /* Return data */ + + if (value_needed) + *value_needed = r.realvaluesize; + + if (data_needed) + *data_needed = r.realdatasize; + + if (data_type) + *data_type = r.type; + + if (value) { + fstring the_value; + + rpcstr_pull(the_value, r.value, sizeof(the_value), -1, + STR_TERMINATE); + + *value = talloc_strdup(mem_ctx, the_value); + } + + if (data) + *data = talloc_memdup(mem_ctx, r.data, r.realdatasize); + + if (data_size) + *data_size = r.realdatasize; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Write data to printer */ + +WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 data_size, char *data, + uint32 *num_written) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_WRITEPRINTER q; + SPOOL_R_WRITEPRINTER r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_writeprinter(&q, hnd, data_size, data); + + /* Marshall data and send request */ + + if (!spoolss_io_q_writeprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_WRITEPRINTER, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_writeprinter("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + if (num_written) + *num_written = r.buffer_written; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/* Delete printer data */ + +WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *valuename) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_DELETEPRINTERDATA q; + SPOOL_R_DELETEPRINTERDATA r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_deleteprinterdata(&q, hnd, valuename); + + /* Marshall data and send request */ + + if (!spoolss_io_q_deleteprinterdata("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_DELETEPRINTERDATA, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!spoolss_io_r_deleteprinterdata("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (!W_ERROR_IS_OK(r.status)) + goto done; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +/** @} **/ diff --git a/source3/rpc_client/cli_spoolss_notify.c b/source3/rpc_client/cli_spoolss_notify.c index 320708736e..f03046558e 100644 --- a/source3/rpc_client/cli_spoolss_notify.c +++ b/source3/rpc_client/cli_spoolss_notify.c @@ -1,260 +1,119 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-2000, - * Copyright (C) Jean Francois Micouleau 1998-2000, - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Gerald Carter 2001-2002, + Copyright (C) Tim Potter 2000-2002, + Copyright (C) Andrew Tridgell 1994-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Jean-Francois Micouleau 1999-2000. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -#if 0 -#include "rpc_parse.h" -#include "nterr.h" -#endif -extern pstring global_myname; - -struct msg_info_table { - uint32 msg; - uint32 field; - char* name; - void (*construct_fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data, - print_queue_struct *queue, - NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx); -}; - -struct msg_info_table msg_table[] = { -{ PRINTER_MESSAGE_DRIVER, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_MESSAGE_DRIVER", spoolss_notify_driver_name }, -{ PRINTER_MESSAGE_ATTRIBUTES, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_MESSAGE_ATTRIBUTES", spoolss_notify_attributes }, -{ PRINTER_MESSAGE_COMMENT, PRINTER_NOTIFY_COMMENT, "PRINTER_MESSAGE_COMMENT", spoolss_notify_comment }, -{ PRINTER_MESSAGE_LOCATION, PRINTER_NOTIFY_LOCATION, "PRINTER_MESSAGE_LOCATION", spoolss_notify_location }, -{ PRINTER_MESSAGE_PRINTERNAME, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_MESSAGE_PRINTERNAME", spoolss_notify_printer_name }, -{ PRINTER_MESSAGE_SHARENAME, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_MESSAGE_SHARENAME", spoolss_notify_share_name }, -{ PRINTER_MESSAGE_PORT, PRINTER_NOTIFY_PORT_NAME, "PRINTER_MESSAGE_PORT", spoolss_notify_port_name }, -{ PRINTER_MESSAGE_CJOBS, PRINTER_NOTIFY_CJOBS, "PRINTER_MESSAGE_CJOBS", spoolss_notify_cjobs }, -{ PRINTER_MESSAGE_SEPFILE, PRINTER_NOTIFY_SEPFILE, "PRINTER_MESSAGE_SEPFILE", spoolss_notify_sepfile }, -{ PRINTER_MESSAGE_PARAMS, PRINTER_NOTIFY_PARAMETERS, "PRINTER_MESSAGE_PARAMETERS", spoolss_notify_parameters }, -{ PRINTER_MESSAGE_DATATYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_MESSAGE_DATATYPE", spoolss_notify_datatype }, -{ PRINTER_MESSAGE_NULL, 0x0, "", NULL }, -}; - -/********************************************************* - Disconnect from the client machine. -**********************************************************/ -BOOL spoolss_disconnect_from_client( struct cli_state *cli) -{ - cli_nt_session_close(cli); - cli_ulogoff(cli); - cli_shutdown(cli); - - return True; -} - - -/********************************************************* - Connect to the client machine. -**********************************************************/ - -BOOL spoolss_connect_to_client( struct cli_state *cli, char *remote_machine) -{ - ZERO_STRUCTP(cli); - if(cli_initialise(cli) == NULL) { - DEBUG(0,("connect_to_client: unable to initialize client connection.\n")); - return False; - } - - if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) { - DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine)); - cli_shutdown(cli); - return False; - } - - if (ismyip(cli->dest_ip)) { - DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine)); - cli_shutdown(cli); - return False; - } - - if (!cli_connect(cli, remote_machine, &cli->dest_ip)) { - DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) )); - cli_shutdown(cli); - return False; - } - - if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) { - DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n", - remote_machine)); - return False; - } - - cli->protocol = PROTOCOL_NT1; - - if (!cli_negprot(cli)) { - DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(cli) )); - cli_shutdown(cli); - return False; - } - - if (cli->protocol != PROTOCOL_NT1) { - DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine)); - cli_shutdown(cli); - return False; - } - - /* - * Do an anonymous session setup. - */ - - if (!cli_session_setup(cli, "", "", 0, "", 0, "")) { - DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(cli) )); - cli_shutdown(cli); - return False; - } - - if (!(cli->sec_mode & 1)) { - DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine)); - cli_shutdown(cli); - return False; - } - - if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) { - DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(cli) )); - cli_shutdown(cli); - return False; - } - - /* - * Ok - we have an anonymous connection to the IPC$ share. - * Now start the NT Domain stuff :-). - */ - - if(cli_nt_session_open(cli, PIPE_SPOOLSS) == False) { - DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli))); - cli_nt_session_close(cli); - cli_ulogoff(cli); - cli_shutdown(cli); - return False; - } - - return True; -} /* * SPOOLSS Client RPC's used by servers as the notification - * back channel + * back channel. */ -/*************************************************************************** - do a reply open printer -****************************************************************************/ +/* Send a ReplyOpenPrinter request. This rpc is made by the printer + server to the printer client in response to a rffpcnex request. + The rrfpcnex request names a printer and a handle (the printerlocal + value) and this rpc establishes a back-channel over which printer + notifications are performed. */ WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, - char *printer, uint32 localprinter, uint32 type, - POLICY_HND *handle) + char *printer, uint32 printerlocal, uint32 type, + POLICY_HND *handle) { + prs_struct qbuf, rbuf; + SPOOL_Q_REPLYOPENPRINTER q; + SPOOL_R_REPLYOPENPRINTER r; WERROR result = W_ERROR(ERRgeneral); - prs_struct rbuf; - prs_struct buf; + /* Initialise input parameters */ - SPOOL_Q_REPLYOPENPRINTER q_s; - SPOOL_R_REPLYOPENPRINTER r_s; + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - prs_init(&buf, 1024, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL ); + make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type); - /* create and send a MSRPC command with api SPOOLSS_REPLYOPENPRINTER */ - - /* store the parameters */ - make_spoolss_q_replyopenprinter(&q_s, printer, localprinter, type); + /* Marshall data and send request */ - /* turn parameters into data stream */ - if(!spoolss_io_q_replyopenprinter("", &q_s, &buf, 0)) { - DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to marshall SPOOL_Q_REPLYOPENPRINTER struct.\n")); + if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf)) goto done; - } - - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYOPENPRINTER, &buf, &rbuf)) + + /* Unmarshall response */ + + if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0)) goto done; + + /* Return result */ - /* turn data stream into parameters*/ - if(!spoolss_io_r_replyopenprinter("", &r_s, &rbuf, 0)) { - DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to unmarshall SPOOL_R_REPLYOPENPRINTER struct.\n")); - goto done; - } - - memcpy(handle, &r_s.handle, sizeof(r_s.handle)); - result = r_s.status; + memcpy(handle, &r.handle, sizeof(r.handle)); + result = r.status; done: - prs_mem_free(&buf); + prs_mem_free(&qbuf); prs_mem_free(&rbuf); return result; } -/*************************************************************************** - do a reply open printer -****************************************************************************/ +/* Close a back-channel notification connection */ WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *handle) + POLICY_HND *handle) { + prs_struct qbuf, rbuf; + SPOOL_Q_REPLYCLOSEPRINTER q; + SPOOL_R_REPLYCLOSEPRINTER r; WERROR result = W_ERROR(ERRgeneral); - prs_struct rbuf; - prs_struct buf; - - SPOOL_Q_REPLYCLOSEPRINTER q_s; - SPOOL_R_REPLYCLOSEPRINTER r_s; - prs_init(&buf, 1024, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL ); + /* Initialise input parameters */ - /* create and send a MSRPC command with api */ - - /* store the parameters */ - make_spoolss_q_reply_closeprinter(&q_s, handle); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* turn parameters into data stream */ - if(!spoolss_io_q_replycloseprinter("", &q_s, &buf, 0)) { - DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_Q_REPLY_CLOSEPRINTER struct.\n")); - goto done; - } + make_spoolss_q_reply_closeprinter(&q, handle); - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYCLOSEPRINTER, &buf, &rbuf)) - goto done; + /* Marshall data and send request */ - /* turn data stream into parameters*/ - if(!spoolss_io_r_replycloseprinter("", &r_s, &rbuf, 0)) { - DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_R_REPLY_CLOSEPRINTER struct.\n")); + if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf)) goto done; - } + /* Unmarshall response */ + + if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0)) + goto done; + + /* Return result */ - result = r_s.status; + result = r.status; done: - prs_mem_free(&buf); - prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); return result; } - /********************************************************************* This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change notification event when the registration **did not** use @@ -262,186 +121,147 @@ done: Also see cli_spolss_reply_rrpcn() *********************************************************************/ -WERROR cli_spoolss_routerreplyprinter (struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint32 condition, uint32 changd_id) +WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 condition, uint32 change_id) { prs_struct qbuf, rbuf; SPOOL_Q_ROUTERREPLYPRINTER q; SPOOL_R_ROUTERREPLYPRINTER r; WERROR result = W_ERROR(ERRgeneral); - ZERO_STRUCT(q); - ZERO_STRUCT(r); - - /* Initialise input parameters */ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* write the request */ - make_spoolss_q_routerreplyprinter(&q, pol, condition, changd_id); + make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id); /* Marshall data and send request */ - if (!spoolss_io_q_routerreplyprinter ("", &q, &qbuf, 0)) { - DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to marshall SPOOL_Q_ROUTERREPLYPRINTER!\n")); - goto done; - } - - - if (!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) - goto done; + if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) || + !rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) + goto done; + /* Unmarshall response */ - if (!spoolss_io_r_routerreplyprinter ("", &r, &rbuf, 0)) { - DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to unmarshall SPOOL_R_ROUTERREPLYPRINTER!\n")); + + if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0)) goto done; - } /* Return output parameters */ + result = r.status; - + done: prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + prs_mem_free(&rbuf); return result; } - -/********************************************************************************** - Build the SPOOL_NOTIFY_INFO_DATA entries based upon the flags which have been set - *********************************************************************************/ - -static int build_notify_data (TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, uint32 flags, - SPOOL_NOTIFY_INFO_DATA **notify_data) -{ - SPOOL_NOTIFY_INFO_DATA *data; - uint32 idx = 0; - int i = 0; - - while ((msg_table[i].msg != PRINTER_MESSAGE_NULL) && flags) - { - if (flags & msg_table[i].msg) - { - DEBUG(10,("build_notify_data: %s set on [%s][%d]\n", msg_table[i].name, - printer->info_2->printername, idx)); - if ((data=Realloc(*notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) { - DEBUG(0,("build_notify_data: Realloc() failed with size [%d]!\n", - (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))); - return -1; - } - *notify_data = data; - - /* clear memory */ - memset(*notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA)); - - /* - * 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE - * See PRINTER_NOTIFY_INFO_DATA entries in MSDN - * --jerry - */ - construct_info_data(*notify_data+idx, PRINTER_NOTIFY_TYPE, msg_table[i].field, 0x00); - - msg_table[i].construct_fn(-1, *notify_data+idx, NULL, printer, ctx); - idx++; - } - - i++; - } - - return idx; -} - /********************************************************************* - This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change + This SPOOLSS_REPLY_RRPCN function is used to send a change notification event when the registration **did** use SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor Also see cli_spoolss_routereplyprinter() *********************************************************************/ -WERROR cli_spoolss_reply_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *handle, PRINTER_MESSAGE_INFO *info, - NT_PRINTER_INFO_LEVEL *printer) +WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 notify_data_len, + SPOOL_NOTIFY_INFO_DATA *notify_data, + uint32 change_low, uint32 change_high) { - prs_struct rbuf; - prs_struct buf; - + prs_struct qbuf, rbuf; + SPOOL_Q_REPLY_RRPCN q; + SPOOL_R_REPLY_RRPCN r; + WERROR result = W_ERROR(ERRgeneral); SPOOL_NOTIFY_INFO notify_info; - SPOOL_NOTIFY_INFO_DATA *notify_data = NULL; - uint32 data_len; - WERROR result = W_ERROR(ERRgeneral); + ZERO_STRUCT(q); + ZERO_STRUCT(r); - SPOOL_Q_REPLY_RRPCN q_s; - SPOOL_R_REPLY_RRPCN r_s; + /* Initialise parse structures */ - if (!info) { - DEBUG(5,("cli_spoolss_reply_rrpcn: NULL printer message info pointer!\n")); - goto done; - } - - prs_init(&buf, 1024, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL ); + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); ZERO_STRUCT(notify_info); -/* - * See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX - * events. --jerry -*/ - DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_MESSAGE flags = 0x%8x\n", info->flags)); + /* Initialise input parameters */ - data_len = build_notify_data(mem_ctx, printer, info->flags, ¬ify_data); - if (info->flags && (data_len == -1)) { - DEBUG(0,("cli_spoolss_reply_rrpcn: Failed to build SPOOL_NOTIFY_INFO_DATA [flags == 0x%x] for printer [%s]\n", - info->flags, info->printer_name)); - result = WERR_NOMEM; - goto done; - } notify_info.version = 0x2; notify_info.flags = 0x00020000; /* ?? */ - notify_info.count = data_len; + notify_info.count = notify_data_len; notify_info.data = notify_data; /* create and send a MSRPC command with api */ /* store the parameters */ - make_spoolss_q_reply_rrpcn(&q_s, handle, info->low, info->high, ¬ify_info); + make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high, + ¬ify_info); - /* turn parameters into data stream */ - if(!spoolss_io_q_reply_rrpcn("", &q_s, &buf, 0)) { - DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n")); - goto done; - } + /* Marshall data and send request */ - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &buf, &rbuf)) + if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf)) goto done; + /* Unmarshall response */ - /* turn data stream into parameters*/ - if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) { - DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n")); + if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0)) goto done; - } - if (r_s.unknown0 == 0x00080000) { + if (r.unknown0 == 0x00080000) DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n")); - } - result = r_s.status; + result = r.status; done: - prs_mem_free(&buf); + prs_mem_free(&qbuf); prs_mem_free(&rbuf); - /* - * The memory allocated in this array is talloc'd so we only need - * free the array here. JRA. - */ - SAFE_FREE(notify_data); return result; } +WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, uint32 flags, uint32 options, + char *localmachine, uint32 printerlocal, + SPOOL_NOTIFY_OPTION *option) +{ + prs_struct qbuf, rbuf; + SPOOL_Q_RFFPCNEX q; + SPOOL_R_RFFPCNEX r; + WERROR result = W_ERROR(ERRgeneral); + + 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 */ + + make_spoolss_q_rffpcnex( + &q, pol, flags, options, localmachine, printerlocal, + option); + + /* Marshall data and send request */ + + if(!spoolss_io_q_rffpcnex("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SPOOLSS_RFFPCNEX, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if(!spoolss_io_r_rffpcnex("", &r, &rbuf, 0)) + goto done; + + result = r.status; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c index 06e733893e..1bdd19620b 100644 --- a/source3/rpc_client/cli_srvsvc.c +++ b/source3/rpc_client/cli_srvsvc.c @@ -1,404 +1,445 @@ /* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 1999. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + Unix SMB/CIFS implementation. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Tim Potter 2001 + Copyright (C) Jim McDonough 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_CLI - -/**************************************************************************** -do a server net conn enum -****************************************************************************/ -BOOL do_srv_net_srv_conn_enum(struct cli_state *cli, - char *server_name, char *qual_name, - uint32 switch_value, SRV_CONN_INFO_CTR *ctr, - uint32 preferred_len, - ENUM_HND *hnd) +NTSTATUS cli_srvsvc_net_srv_get_info(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + uint32 switch_value, SRV_INFO_CTR *ctr) { - prs_struct data; - prs_struct rdata; - SRV_Q_NET_CONN_ENUM q_o; - SRV_R_NET_CONN_ENUM r_o; - - if (server_name == NULL || ctr == NULL || preferred_len == 0) - return False; - - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SRV_NET_CONN_ENUM */ - - DEBUG(4,("SRV Net Server Connection Enum(%s, %s), level %d, enum:%8x\n", - server_name, qual_name, switch_value, get_enum_hnd(hnd))); - - ctr->switch_value = switch_value; - ctr->ptr_conn_ctr = 1; - ctr->conn.info0.num_entries_read = 0; - ctr->conn.info0.ptr_conn_info = 1; - - /* store the parameters */ - init_srv_q_net_conn_enum(&q_o, server_name, qual_name, - switch_value, ctr, - preferred_len, - hnd); - - /* turn parameters into data stream */ - if(!srv_io_q_net_conn_enum("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + prs_struct qbuf, rbuf; + SRV_Q_NET_SRV_GET_INFO q; + SRV_R_NET_SRV_GET_INFO r; + NTSTATUS result; - /* send the data on \PIPE\ */ - if(!rpc_api_pipe_req(cli, SRV_NET_CONN_ENUM, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_mem_free(&data); + /* Initialise parse structures */ - r_o.ctr = ctr; + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if(!srv_io_r_net_conn_enum("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } + /* Initialise input parameters */ + + init_srv_q_net_srv_get_info(&q, cli->srv_name_slash, switch_value); - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; + /* Marshall data and send request */ + + if (!srv_io_q_net_srv_get_info("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_SRV_GET_INFO, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - if (r_o.ctr->switch_value != switch_value) { - /* different switch levels. oops. */ - DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: info class %d does not match request %d\n", - r_o.ctr->switch_value, switch_value)); - prs_mem_free(&rdata); - return False; + /* Unmarshall response */ + + r.ctr = ctr; + + if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - prs_mem_free(&rdata); - - return True; -} + result = werror_to_ntstatus(r.status); + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); -/**************************************************************************** -do a server net sess enum -****************************************************************************/ + return result; +} -BOOL do_srv_net_srv_sess_enum(struct cli_state *cli, - char *server_name, char *qual_name, - char *user_name, - uint32 switch_value, SRV_SESS_INFO_CTR *ctr, - uint32 preferred_len, - ENUM_HND *hnd) +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 data; - prs_struct rdata; - SRV_Q_NET_SESS_ENUM q_o; - SRV_R_NET_SESS_ENUM r_o; - - if (server_name == NULL || ctr == NULL || preferred_len == 0) - return False; - - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SRV_NET_SESS_ENUM */ - - DEBUG(4,("SRV Net Session Enum (%s), level %d, enum:%8x\n", - server_name, switch_value, get_enum_hnd(hnd))); - - ctr->switch_value = switch_value; - ctr->ptr_sess_ctr = 1; - ctr->sess.info0.num_entries_read = 0; - ctr->sess.info0.ptr_sess_info = 1; - - /* store the parameters */ - init_srv_q_net_sess_enum(&q_o, server_name, qual_name, user_name, - switch_value, ctr, - preferred_len, - hnd); - - /* turn parameters into data stream */ - if(!srv_io_q_net_sess_enum("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + prs_struct qbuf, rbuf; + SRV_Q_NET_SHARE_ENUM q; + SRV_R_NET_SHARE_ENUM r; + WERROR result = W_ERROR(ERRgeneral); + int i; - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SRV_NET_SESS_ENUM, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_mem_free(&data); + /* Initialise parse structures */ - r_o.ctr = ctr; + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if(!srv_io_r_net_sess_enum("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } + /* 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); - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; - } + 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)); - if (r_o.ctr->switch_value != switch_value) { - /* different switch levels. oops. */ - DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: info class %d does not match request %d\n", - r_o.ctr->switch_value, switch_value)); - prs_mem_free(&rdata); - return False; + /* 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, strlen(s) + 1); + + 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, strlen(s) + 1); + + } + + 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, strlen(s) + 1); + + 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, strlen(s) + 1); + + 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, strlen(s) + 1); + + 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, strlen(s) + 1); + } + break; } + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); - prs_mem_free(&rdata); - - return True; + return result; } -/**************************************************************************** -do a server net share enum -****************************************************************************/ -BOOL do_srv_net_srv_share_enum(struct cli_state *cli, - char *server_name, - uint32 switch_value, SRV_R_NET_SHARE_ENUM *r_o, - uint32 preferred_len, ENUM_HND *hnd) +WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx, + const char *sharename) { - prs_struct data; - prs_struct rdata; - SRV_Q_NET_SHARE_ENUM q_o; - - if (server_name == NULL || preferred_len == 0) - return False; - - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SRV_NET_SHARE_ENUM */ - - DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n", - server_name, switch_value, get_enum_hnd(hnd))); - - /* store the parameters */ - init_srv_q_net_share_enum(&q_o, server_name, switch_value, - preferred_len, hnd); - - /* turn parameters into data stream */ - if(!srv_io_q_net_share_enum("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + prs_struct qbuf, rbuf; + SRV_Q_NET_SHARE_DEL q; + SRV_R_NET_SHARE_DEL r; + WERROR result = W_ERROR(ERRgeneral); - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_mem_free(&data); + /* Initialise parse structures */ - if(!srv_io_r_net_share_enum("", r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } - - if (r_o->status != 0) { - /* report error code */ - DEBUG(0,("SRV_R_NET_SHARE_ENUM: %s\n", nt_errstr(r_o->status))); - prs_mem_free(&rdata); - return False; - } + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if (r_o->ctr.switch_value != switch_value) { - /* different switch levels. oops. */ - DEBUG(0,("SRV_R_NET_SHARE_ENUM: info class %d does not match request %d\n", - r_o->ctr.switch_value, switch_value)); - prs_mem_free(&rdata); - return False; - } + /* Initialise input parameters */ - prs_mem_free(&rdata); - - return True; + init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename); + + /* Marshall data and send request */ + + if (!srv_io_q_net_share_del("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_SHARE_DEL, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!srv_io_r_net_share_del("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/**************************************************************************** -do a server net file enum -****************************************************************************/ +WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *netname, uint32 type, char *remark, + uint32 perms, uint32 max_uses, uint32 num_uses, + char *path, char *passwd) +{ + prs_struct qbuf, rbuf; + SRV_Q_NET_SHARE_ADD q; + SRV_R_NET_SHARE_ADD r; + WERROR result = W_ERROR(ERRgeneral); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); -BOOL do_srv_net_srv_file_enum(struct cli_state *cli, - char *server_name, char *qual_name, - uint32 switch_value, SRV_FILE_INFO_CTR *ctr, - uint32 preferred_len, - ENUM_HND *hnd) + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark, + perms, max_uses, num_uses, path, passwd); + + /* Marshall data and send request */ + + if (!srv_io_q_net_share_add("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_SHARE_ADD, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!srv_io_r_net_share_add("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx, + char *server, TIME_OF_DAY_INFO *tod) { - prs_struct data; - prs_struct rdata; - SRV_Q_NET_FILE_ENUM q_o; - SRV_R_NET_FILE_ENUM r_o; - - if (server_name == NULL || ctr == NULL || preferred_len == 0) - return False; - - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api SRV_NET_FILE_ENUM */ - - DEBUG(4,("SRV Get File Info (%s), level %d, enum:%8x\n", - server_name, switch_value, get_enum_hnd(hnd))); - - q_o.file_level = switch_value; - - ctr->switch_value = switch_value; - ctr->ptr_file_ctr = 1; - ctr->file.info3.num_entries_read = 0; - ctr->file.info3.ptr_file_info = 1; - - /* store the parameters */ - init_srv_q_net_file_enum(&q_o, server_name, qual_name, - switch_value, ctr, - preferred_len, - hnd); - - /* turn parameters into data stream */ - if(!srv_io_q_net_file_enum("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + prs_struct qbuf, rbuf; + SRV_Q_NET_REMOTE_TOD q; + SRV_R_NET_REMOTE_TOD r; + WERROR result = W_ERROR(ERRgeneral); - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_mem_free(&data); + /* Initialise parse structures */ - r_o.ctr = ctr; + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - if(!srv_io_r_net_file_enum("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } - - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SRV_R_NET_FILE_ENUM: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; - } + /* Initialise input parameters */ - if (r_o.ctr->switch_value != switch_value) { - /* different switch levels. oops. */ - DEBUG(0,("SRV_R_NET_FILE_ENUM: info class %d does not match request %d\n", - r_o.ctr->switch_value, switch_value)); - prs_mem_free(&rdata); - return False; - } + init_srv_q_net_remote_tod(&q, cli->srv_name_slash); - prs_mem_free(&rdata); - - return True; + /* Marshall data and send request */ + + if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_REMOTE_TOD, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + r.tod = tod; + + if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0)) + goto done; + + result = r.status; + + if (!W_ERROR_IS_OK(result)) + goto done; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; } -/**************************************************************************** -do a server get info -****************************************************************************/ -BOOL do_srv_net_srv_get_info(struct cli_state *cli, - char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr) +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 data; - prs_struct rdata; - SRV_Q_NET_SRV_GET_INFO q_o; - SRV_R_NET_SRV_GET_INFO r_o; + prs_struct qbuf, rbuf; + SRV_Q_NET_FILE_ENUM q; + SRV_R_NET_FILE_ENUM r; + WERROR result = W_ERROR(ERRgeneral); + int i; - if (server_name == NULL || switch_value == 0 || ctr == NULL) - return False; + ZERO_STRUCT(q); + ZERO_STRUCT(r); - prs_init(&data, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); + /* Initialise parse structures */ - /* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */ + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value)); + /* Initialise input parameters */ - /* store the parameters */ - init_srv_q_net_srv_get_info(&q_o, server_name, switch_value); + init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name, + file_level, ctr, preferred_len, hnd); - /* turn parameters into data stream */ - if(!srv_io_q_net_srv_get_info("", &q_o, &data, 0)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + /* Marshall data and send request */ - /* send the data on \PIPE\ */ - if (!rpc_api_pipe_req(cli, SRV_NET_SRV_GET_INFO, &data, &rdata)) { - prs_mem_free(&data); - prs_mem_free(&rdata); - return False; - } + if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &qbuf, &rbuf)) + goto done; - prs_mem_free(&data); + /* Unmarshall response */ - r_o.ctr = ctr; + if (!srv_io_r_net_file_enum("", &r, &rbuf, 0)) + goto done; - if(!srv_io_r_net_srv_get_info("", &r_o, &rdata, 0)) { - prs_mem_free(&rdata); - return False; - } + result = r.status; - if (r_o.status != 0) { - /* report error code */ - DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rdata); - return False; - } + if (!W_ERROR_IS_OK(result)) + goto done; - if (r_o.ctr->switch_value != q_o.switch_value) { - /* different switch levels. oops. */ - DEBUG(0,("SRV_R_NET_SRV_GET_INFO: info class %d does not match request %d\n", - r_o.ctr->switch_value, q_o.switch_value)); - prs_mem_free(&rdata); - return False; - } + /* copy the data over to the ctr */ + + ZERO_STRUCTP(ctr); + + ctr->switch_value = file_level; - prs_mem_free(&rdata); + ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries; - return True; + 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, strlen(s) + 1); + + 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, strlen(s) + 1); + + } + + break; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 file_id) +{ + prs_struct qbuf, rbuf; + SRV_Q_NET_FILE_CLOSE q; + SRV_R_NET_FILE_CLOSE r; + WERROR result = W_ERROR(ERRgeneral); + + 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_close(&q, cli->srv_name_slash, file_id); + + /* Marshall data and send request */ + + if (!srv_io_q_net_file_close("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SRV_NET_FILE_CLOSE, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if (!srv_io_r_net_file_close("", &r, &rbuf, 0)) + goto done; + + result = r.status; + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + return result; } diff --git a/source3/rpc_client/cli_wkssvc.c b/source3/rpc_client/cli_wkssvc.c index 90269dfbee..97b948bf62 100644 --- a/source3/rpc_client/cli_wkssvc.c +++ b/source3/rpc_client/cli_wkssvc.c @@ -1,87 +1,93 @@ /* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1997, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 1999. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + Unix SMB/CIFS implementation. + NT Domain Authentication SMB / MSRPC client + Copyright (C) Andrew Tridgell 1994-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996-2000 + Copyright (C) Tim Potter 2001 + Copytight (C) Rafal Szczesniak 2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ #include "includes.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_RPC_CLI - -/**************************************************************************** -do a WKS Open Policy -****************************************************************************/ -BOOL do_wks_query_info(struct cli_state *cli, - char *server_name, uint32 switch_value, - WKS_INFO_100 *wks100) +/** + * WksQueryInfo rpc call (like query for server's capabilities) + * + * @param initialised client structure with \PIPE\wkssvc opened + * @param mem_ctx memory context assigned to this rpc binding + * @param wks100 WksQueryInfo structure + * + * @return NTSTATUS of rpc call + */ + +NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + WKS_INFO_100 *wks100) { + prs_struct buf; prs_struct rbuf; - prs_struct buf; WKS_Q_QUERY_INFO q_o; WKS_R_QUERY_INFO r_o; - if (server_name == 0 || wks100 == NULL) - return False; - - prs_init(&buf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL ); - - /* create and send a MSRPC command with api WKS_QUERY_INFO */ - - DEBUG(4,("WKS Query Info\n")); + if (cli == NULL || wks100 == NULL) + return NT_STATUS_UNSUCCESSFUL; - /* store the parameters */ - init_wks_q_query_info(&q_o, server_name, switch_value); + /* init rpc parse structures */ + prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* turn parameters into data stream */ - if(!wks_io_q_query_info("", &q_o, &buf, 0)) { + DEBUG(4, ("WksQueryInfo\n")); + + /* init query structure with rpc call arguments */ + init_wks_q_query_info(&q_o, cli->desthost, 100); + + /* marshall data */ + if (!wks_io_q_query_info("", &q_o, &buf, 0)) { prs_mem_free(&buf); prs_mem_free(&rbuf); - return False; + return NT_STATUS_UNSUCCESSFUL; } - - /* send the data on \PIPE\ */ + + /* actual rpc call over \PIPE\wkssvc */ if (!rpc_api_pipe_req(cli, WKS_QUERY_INFO, &buf, &rbuf)) { prs_mem_free(&buf); prs_mem_free(&rbuf); - return False; + return NT_STATUS_UNSUCCESSFUL; } - + prs_mem_free(&buf); r_o.wks100 = wks100; - if(!wks_io_r_query_info("", &r_o, &rbuf, 0)) { + /* get call results from response buffer */ + if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) { prs_mem_free(&rbuf); - return False; + return NT_STATUS_UNSUCCESSFUL; } - - if (r_o.status != 0) { - /* report error code */ + + /* check returnet status code */ + if (NT_STATUS_IS_ERR(r_o.status)) { + /* report the error */ DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r_o.status))); prs_mem_free(&rbuf); - return False; + return r_o.status; } - + + /* do clean up */ prs_mem_free(&rbuf); - - return True; + + return NT_STATUS_OK; } + -- cgit