mirror of
https://github.com/samba-team/samba.git
synced 2025-02-23 09:57:40 +03:00
removed a bunch of the old rpc code in preparation for replacing it all with auto-generated code
(This used to be commit 874bf4689d2816474b33eb1ac21530186319ed62)
This commit is contained in:
parent
aeda2f8152
commit
062670f00c
@ -215,19 +215,12 @@ LIBRAW_OBJ = libcli/raw/rawfile.o libcli/raw/smb_signing.o \
|
|||||||
|
|
||||||
LIBSMB_OBJ = libcli/clireadwrite.o libcli/cliconnect.o \
|
LIBSMB_OBJ = libcli/clireadwrite.o libcli/cliconnect.o \
|
||||||
libcli/clifile.o libcli/clilist.o libcli/clitrans2.o \
|
libcli/clifile.o libcli/clilist.o libcli/clitrans2.o \
|
||||||
libcli/clisecdesc.o libcli/climessage.o \
|
libcli/climessage.o \
|
||||||
libcli/clideltree.o \
|
libcli/clideltree.o \
|
||||||
$(LIBRAW_OBJ)
|
$(LIBRAW_OBJ)
|
||||||
|
|
||||||
# LIBDFS_OBJ = libcli/clidfs.o
|
# LIBDFS_OBJ = libcli/clidfs.o
|
||||||
|
|
||||||
LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
|
|
||||||
rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
|
|
||||||
rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \
|
|
||||||
rpc_client/cli_reg.o rpc_client/cli_pipe.o \
|
|
||||||
rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \
|
|
||||||
rpc_client/cli_ds.o libcli/namequery_dc.o
|
|
||||||
|
|
||||||
#LIBMSRPC_SERVER_OBJ = libcli/trust_passwd.o
|
#LIBMSRPC_SERVER_OBJ = libcli/trust_passwd.o
|
||||||
|
|
||||||
#REGOBJS_OBJ = registry/reg_objects.o
|
#REGOBJS_OBJ = registry/reg_objects.o
|
||||||
@ -250,9 +243,6 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
|
|||||||
#RPC_DFS_OBJ = rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o
|
#RPC_DFS_OBJ = rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o
|
||||||
#RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o
|
#RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o
|
||||||
|
|
||||||
RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \
|
|
||||||
rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
|
|
||||||
|
|
||||||
# These are like they are to avoid a dependency on GNU MAKE
|
# These are like they are to avoid a dependency on GNU MAKE
|
||||||
@LSA_DYNAMIC_YES@RPC_MODULES1 = bin/librpc_lsarpc.@SHLIBEXT@
|
@LSA_DYNAMIC_YES@RPC_MODULES1 = bin/librpc_lsarpc.@SHLIBEXT@
|
||||||
@NETLOG_DYNAMIC_YES@RPC_MODULES2 = bin/librpc_NETLOGON.@SHLIBEXT@
|
@NETLOG_DYNAMIC_YES@RPC_MODULES2 = bin/librpc_NETLOGON.@SHLIBEXT@
|
||||||
@ -277,20 +267,6 @@ RPC_SERVER_OBJ = $(RPC_PIPE_OBJ1) $(RPC_PIPE_OBJ2) $(RPC_PIPE_OBJ3) \
|
|||||||
$(RPC_PIPE_OBJ4) $(RPC_PIPE_OBJ5) $(RPC_PIPE_OBJ6) $(RPC_PIPE_OBJ7) \
|
$(RPC_PIPE_OBJ4) $(RPC_PIPE_OBJ5) $(RPC_PIPE_OBJ6) $(RPC_PIPE_OBJ7) \
|
||||||
$(RPC_PIPE_OBJ8) $(RPC_PIPE_OBJ)
|
$(RPC_PIPE_OBJ8) $(RPC_PIPE_OBJ)
|
||||||
|
|
||||||
# this includes only the low level parse code, not stuff
|
|
||||||
# that requires knowledge of security contexts
|
|
||||||
RPC_PARSE_OBJ1 = rpc_parse/parse_prs.o rpc_parse/parse_sec.o \
|
|
||||||
rpc_parse/parse_misc.o
|
|
||||||
|
|
||||||
RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
|
|
||||||
rpc_parse/parse_reg.o rpc_parse/parse_rpc.o \
|
|
||||||
rpc_parse/parse_samr.o rpc_parse/parse_srv.o \
|
|
||||||
rpc_parse/parse_wks.o rpc_parse/parse_ds.o \
|
|
||||||
rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
|
|
||||||
$(REGOBJS_OBJ)
|
|
||||||
|
|
||||||
|
|
||||||
RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
|
|
||||||
|
|
||||||
#LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
|
#LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
|
||||||
|
|
||||||
|
@ -629,3 +629,18 @@ void print_guid(GUID *guid)
|
|||||||
d_printf("%02x", guid->info[i]);
|
d_printf("%02x", guid->info[i]);
|
||||||
d_printf("\n");
|
d_printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Check if ACE has OBJECT type.
|
||||||
|
********************************************************************/
|
||||||
|
BOOL sec_ace_object(uint8 type)
|
||||||
|
{
|
||||||
|
if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
|
||||||
|
type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
|
||||||
|
type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
|
||||||
|
type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
@ -1,247 +0,0 @@
|
|||||||
/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
RPC pipe client
|
|
||||||
Copyright (C) Tim Potter 2000-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"
|
|
||||||
|
|
||||||
/* Query DFS support */
|
|
||||||
|
|
||||||
NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
BOOL *dfs_exists)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DFS_Q_DFS_EXIST q;
|
|
||||||
DFS_R_DFS_EXIST 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_dfs_q_dfs_exist(&q);
|
|
||||||
|
|
||||||
if (!dfs_io_q_dfs_exist("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, DFS_EXIST, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_exist("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
*dfs_exists = (r.status != 0);
|
|
||||||
|
|
||||||
result = NT_STATUS_OK;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *entrypath, const char *servername,
|
|
||||||
const char *sharename, const char *comment, uint32 flags)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DFS_Q_DFS_ADD q;
|
|
||||||
DFS_R_DFS_ADD 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_dfs_q_dfs_add(&q, entrypath, servername, sharename, comment,
|
|
||||||
flags);
|
|
||||||
|
|
||||||
if (!dfs_io_q_dfs_add("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, DFS_ADD, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_add("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
result = werror_to_ntstatus(r.status);
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *entrypath, const char *servername,
|
|
||||||
const char *sharename)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DFS_Q_DFS_REMOVE q;
|
|
||||||
DFS_R_DFS_REMOVE 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_dfs_q_dfs_remove(&q, entrypath, servername, sharename);
|
|
||||||
|
|
||||||
if (!dfs_io_q_dfs_remove("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, DFS_REMOVE, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_remove("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
result = werror_to_ntstatus(r.status);
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *entrypath, const char *servername,
|
|
||||||
const char *sharename, uint32 info_level,
|
|
||||||
DFS_INFO_CTR *ctr)
|
|
||||||
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DFS_Q_DFS_GET_INFO q;
|
|
||||||
DFS_R_DFS_GET_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_dfs_q_dfs_get_info(&q, entrypath, servername, sharename,
|
|
||||||
info_level);
|
|
||||||
|
|
||||||
if (!dfs_io_q_dfs_get_info("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, DFS_GET_INFO, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_get_info("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
result = werror_to_ntstatus(r.status);
|
|
||||||
*ctr = r.ctr;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enumerate dfs shares */
|
|
||||||
|
|
||||||
NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
uint32 info_level, DFS_INFO_CTR *ctr)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DFS_Q_DFS_ENUM q;
|
|
||||||
DFS_R_DFS_ENUM 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_dfs_q_dfs_enum(&q, info_level, ctr);
|
|
||||||
|
|
||||||
if (!dfs_io_q_dfs_enum("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, DFS_ENUM, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
r.ctr = ctr;
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_enum("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
result = werror_to_ntstatus(r.status);
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
RPC pipe client
|
|
||||||
Copyright (C) Gerald Carter 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"
|
|
||||||
|
|
||||||
/* implementations of client side DsXXX() functions */
|
|
||||||
|
|
||||||
NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
uint16 level, DS_DOMINFO_CTR *ctr)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
DS_Q_GETPRIMDOMINFO q;
|
|
||||||
DS_R_GETPRIMDOMINFO r;
|
|
||||||
NTSTATUS result;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
q.level = level;
|
|
||||||
|
|
||||||
if (!ds_io_q_getprimdominfo("", &q, &qbuf, 0)
|
|
||||||
|| !rpc_api_pipe_req(cli, DS_GETPRIMDOMINFO, &qbuf, &rbuf)) {
|
|
||||||
result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!ds_io_r_getprimdominfo("", &r, &rbuf, 0)) {
|
|
||||||
result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return basic info - if we are requesting at info != 1 then
|
|
||||||
there could be trouble. */
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
if (ctr) {
|
|
||||||
ctr->basic = talloc(mem_ctx, sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
|
|
||||||
if (!ctr->basic)
|
|
||||||
goto done;
|
|
||||||
memcpy(ctr->basic, r.info.basic, sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,759 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
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",
|
|
||||||
lp_netbios_name(), cli->desthost, credstr(clnt_chal->data)));
|
|
||||||
|
|
||||||
/* store the parameters */
|
|
||||||
init_q_req_chal(&q, cli->srv_name_slash, lp_netbios_name(), 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;
|
|
||||||
|
|
||||||
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, lp_netbios_name(),
|
|
||||||
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, lp_netbios_name(), &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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
LSA Authenticate 3
|
|
||||||
|
|
||||||
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_auth3(struct cli_state *cli,
|
|
||||||
uint16 sec_chan,
|
|
||||||
uint32 *neg_flags, DOM_CHAL *srv_chal)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
NET_Q_AUTH_3 q;
|
|
||||||
NET_R_AUTH_3 r;
|
|
||||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
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_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
|
|
||||||
cli->srv_name_slash, cli->mach_acct, sec_chan, lp_netbios_name(),
|
|
||||||
credstr(cli->clnt_cred.challenge.data), *neg_flags));
|
|
||||||
|
|
||||||
/* store the parameters */
|
|
||||||
init_q_auth_3(&q, cli->srv_name_slash, cli->mach_acct,
|
|
||||||
sec_chan, lp_netbios_name(), &cli->clnt_cred.challenge,
|
|
||||||
*neg_flags);
|
|
||||||
|
|
||||||
/* turn parameters into data stream */
|
|
||||||
|
|
||||||
if (!net_io_q_auth_3("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, NET_AUTH3, &qbuf, &rbuf)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!net_io_r_auth_3("", &r, &rbuf, 0)) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
*neg_flags = r.srv_flgs.neg_flags;
|
|
||||||
|
|
||||||
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_auth3: 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the secure channel type depending on the server role. */
|
|
||||||
|
|
||||||
uint16 get_sec_chan(void)
|
|
||||||
{
|
|
||||||
uint16 sec_chan = SEC_CHAN_WKSTA;
|
|
||||||
|
|
||||||
switch (lp_server_role()) {
|
|
||||||
case ROLE_DOMAIN_PDC:
|
|
||||||
sec_chan = SEC_CHAN_DOMAIN;
|
|
||||||
break;
|
|
||||||
case ROLE_DOMAIN_BDC:
|
|
||||||
sec_chan = SEC_CHAN_BDC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sec_chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize domain session credentials */
|
|
||||||
|
|
||||||
NTSTATUS cli_nt_setup_creds(struct cli_state *cli,
|
|
||||||
uint16 sec_chan,
|
|
||||||
const unsigned char mach_pwd[16], uint32 *neg_flags, int level)
|
|
||||||
{
|
|
||||||
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/3 ********************/
|
|
||||||
|
|
||||||
/* calculate auth-2/3 credentials */
|
|
||||||
zerotime.time = 0;
|
|
||||||
cred_create(cli->sess_key, &clnt_chal, zerotime, &cli->clnt_cred.challenge);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send client auth-2/3 challenge.
|
|
||||||
* Receive an auth-2/3 challenge response and check it.
|
|
||||||
*/
|
|
||||||
switch (level) {
|
|
||||||
case 2:
|
|
||||||
result = cli_net_auth2(cli, sec_chan, *neg_flags, &srv_chal);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
result = cli_net_auth3(cli, sec_chan, neg_flags, &srv_chal);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DEBUG(1,("cli_nt_setup_creds: unsupported auth level: %d\n", level));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(result))
|
|
||||||
DEBUG(1,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, 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. 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)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Create the new client credentials.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cli->clnt_cred.timestamp.time = time(NULL);
|
|
||||||
|
|
||||||
memcpy(new_clnt_cred, &cli->clnt_cred, sizeof(*new_clnt_cred));
|
|
||||||
|
|
||||||
/* Calculate the new credentials. */
|
|
||||||
cred_create(cli->sess_key, &(cli->clnt_cred.challenge),
|
|
||||||
new_clnt_cred->timestamp, &(new_clnt_cred->challenge));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sam synchronisation */
|
|
||||||
|
|
||||||
NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_CRED *ret_creds,
|
|
||||||
uint32 database_id, uint32 next_rid, uint32 *num_deltas,
|
|
||||||
SAM_DELTA_HDR **hdr_deltas,
|
|
||||||
SAM_DELTA_CTR **deltas)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
NET_Q_SAM_SYNC q;
|
|
||||||
NET_R_SAM_SYNC r;
|
|
||||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
DOM_CRED clnt_creds;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2,
|
|
||||||
&clnt_creds, ret_creds, database_id, next_rid);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
NET_Q_SAM_DELTAS q;
|
|
||||||
NET_R_SAM_DELTAS r;
|
|
||||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
DOM_CRED clnt_creds;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
init_net_q_sam_deltas(&q, cli->srv_name_slash,
|
|
||||||
cli->clnt_name_slash + 2, &clnt_creds,
|
|
||||||
database_id, seqnum);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!net_io_r_sam_deltas("", 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;
|
|
||||||
|
|
||||||
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,
|
|
||||||
const char *username, const 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;
|
|
||||||
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, lp_netbios_name(),
|
|
||||||
&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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
r.user = &user;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
int validation_level = 3;
|
|
||||||
char *workstation_name_slash;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q);
|
|
||||||
ZERO_STRUCT(r);
|
|
||||||
|
|
||||||
workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
|
|
||||||
|
|
||||||
if (!workstation_name_slash) {
|
|
||||||
DEBUG(0, ("talloc_asprintf failed!\n"));
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 = NET_LOGON_TYPE;
|
|
||||||
|
|
||||||
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, lp_netbios_name(),
|
|
||||||
&clnt_creds, &dummy_rtn_creds, NET_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
r.user = info3;
|
|
||||||
|
|
||||||
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.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ));
|
|
||||||
nt_status = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return nt_status;
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
/* Shutdown a server */
|
|
||||||
|
|
||||||
NTSTATUS cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *msg, uint32 timeout, BOOL do_reboot,
|
|
||||||
BOOL force)
|
|
||||||
{
|
|
||||||
prs_struct qbuf;
|
|
||||||
prs_struct rbuf;
|
|
||||||
REG_Q_SHUTDOWN q_s;
|
|
||||||
REG_R_SHUTDOWN r_s;
|
|
||||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
if (msg == NULL) return NT_STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
ZERO_STRUCT (q_s);
|
|
||||||
ZERO_STRUCT (r_s);
|
|
||||||
|
|
||||||
prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
init_reg_q_shutdown(&q_s, msg, timeout, do_reboot, force);
|
|
||||||
|
|
||||||
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 result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Abort a server shutdown */
|
|
||||||
|
|
||||||
NTSTATUS cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx)
|
|
||||||
{
|
|
||||||
prs_struct rbuf;
|
|
||||||
prs_struct qbuf;
|
|
||||||
REG_Q_ABORT_SHUTDOWN q_s;
|
|
||||||
REG_R_ABORT_SHUTDOWN r_s;
|
|
||||||
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
ZERO_STRUCT (q_s);
|
|
||||||
ZERO_STRUCT (r_s);
|
|
||||||
|
|
||||||
prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
init_reg_q_abort_shutdown(&q_s);
|
|
||||||
|
|
||||||
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 result;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,272 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SPOOLSS Client RPC's used by servers as the notification
|
|
||||||
* back channel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 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,
|
|
||||||
const 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);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Return result */
|
|
||||||
|
|
||||||
memcpy(handle, &r.handle, sizeof(r.handle));
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close a back-channel notification connection */
|
|
||||||
|
|
||||||
WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
POLICY_HND *handle)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
SPOOL_Q_REPLYCLOSEPRINTER q;
|
|
||||||
SPOOL_R_REPLYCLOSEPRINTER r;
|
|
||||||
WERROR result = W_ERROR(ERRgeneral);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
make_spoolss_q_reply_closeprinter(&q, handle);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
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.status;
|
|
||||||
|
|
||||||
done:
|
|
||||||
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
|
|
||||||
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor.
|
|
||||||
Also see cli_spolss_reply_rrpcn()
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
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))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Return output parameters */
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
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_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 qbuf, rbuf;
|
|
||||||
SPOOL_Q_REPLY_RRPCN q;
|
|
||||||
SPOOL_R_REPLY_RRPCN r;
|
|
||||||
WERROR result = W_ERROR(ERRgeneral);
|
|
||||||
SPOOL_NOTIFY_INFO notify_info;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
ZERO_STRUCT(notify_info);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
notify_info.version = 0x2;
|
|
||||||
notify_info.flags = 0x00020000; /* ?? */
|
|
||||||
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, pol, change_low, change_high,
|
|
||||||
¬ify_info);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (r.unknown0 == 0x00080000)
|
|
||||||
DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
|
|
||||||
else if ( r.unknown0 != 0x0 )
|
|
||||||
DEBUG(8,("cli_spoolss_reply_rrpcn: unknown0 is non-zero [0x%x]\n", r.unknown0));
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
POLICY_HND *pol, uint32 flags, uint32 options,
|
|
||||||
const 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;
|
|
||||||
}
|
|
@ -1,442 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli,
|
|
||||||
TALLOC_CTX *mem_ctx,
|
|
||||||
uint32 switch_value, SRV_INFO_CTR *ctr)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
SRV_Q_NET_SRV_GET_INFO q;
|
|
||||||
SRV_R_NET_SRV_GET_INFO 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_srv_get_info(&q, cli->srv_name_slash, switch_value);
|
|
||||||
|
|
||||||
/* 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))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
r.ctr = ctr;
|
|
||||||
|
|
||||||
if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
done:
|
|
||||||
prs_mem_free(&qbuf);
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
|
|
||||||
int preferred_len, ENUM_HND *hnd)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
SRV_Q_NET_SHARE_ENUM q;
|
|
||||||
SRV_R_NET_SHARE_ENUM r;
|
|
||||||
WERROR result = W_ERROR(ERRgeneral);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q);
|
|
||||||
ZERO_STRUCT(r);
|
|
||||||
|
|
||||||
/* Initialise parse structures */
|
|
||||||
|
|
||||||
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
init_srv_q_net_share_enum(
|
|
||||||
&q, cli->srv_name_slash, info_level, preferred_len, hnd);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
if (!W_ERROR_IS_OK(result))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Oh yuck yuck yuck - we have to copy all the info out of the
|
|
||||||
SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
|
|
||||||
prs_mem_free() it will all be invalidated. The various share
|
|
||||||
info structures suck badly too. This really is gross. */
|
|
||||||
|
|
||||||
ZERO_STRUCTP(ctr);
|
|
||||||
|
|
||||||
if (!r.ctr.num_entries)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
ctr->info_level = info_level;
|
|
||||||
ctr->num_entries = r.ctr.num_entries;
|
|
||||||
|
|
||||||
switch(info_level) {
|
|
||||||
case 1:
|
|
||||||
ctr->share.info1 = (SRV_SHARE_INFO_1 *)talloc(
|
|
||||||
mem_ctx, sizeof(SRV_SHARE_INFO_1) * ctr->num_entries);
|
|
||||||
|
|
||||||
memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
|
|
||||||
|
|
||||||
for (i = 0; i < ctr->num_entries; i++) {
|
|
||||||
SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
/* Copy pointer crap */
|
|
||||||
|
|
||||||
memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1,
|
|
||||||
sizeof(SH_INFO_1));
|
|
||||||
|
|
||||||
/* Duplicate strings */
|
|
||||||
|
|
||||||
s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
|
|
||||||
if (s)
|
|
||||||
init_unistr2(&info1->info_1_str.uni_netname, s, 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);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *sharename)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
SRV_Q_NET_SHARE_DEL q;
|
|
||||||
SRV_R_NET_SHARE_DEL 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_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
const char *netname, uint32 type,
|
|
||||||
const char *remark, uint32 perms,
|
|
||||||
uint32 max_uses, uint32 num_uses,
|
|
||||||
const char *path, const 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);
|
|
||||||
|
|
||||||
/* 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 qbuf, rbuf;
|
|
||||||
SRV_Q_NET_REMOTE_TOD q;
|
|
||||||
SRV_R_NET_REMOTE_TOD 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_remote_tod(&q, cli->srv_name_slash);
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
|
||||||
uint32 file_level, const char *user_name,
|
|
||||||
SRV_FILE_INFO_CTR *ctr, int preferred_len,
|
|
||||||
ENUM_HND *hnd)
|
|
||||||
{
|
|
||||||
prs_struct qbuf, rbuf;
|
|
||||||
SRV_Q_NET_FILE_ENUM q;
|
|
||||||
SRV_R_NET_FILE_ENUM r;
|
|
||||||
WERROR result = W_ERROR(ERRgeneral);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q);
|
|
||||||
ZERO_STRUCT(r);
|
|
||||||
|
|
||||||
/* Initialise parse structures */
|
|
||||||
|
|
||||||
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
/* Initialise input parameters */
|
|
||||||
|
|
||||||
init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name,
|
|
||||||
file_level, ctr, preferred_len, hnd);
|
|
||||||
|
|
||||||
/* Marshall data and send request */
|
|
||||||
|
|
||||||
if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
|
|
||||||
!rpc_api_pipe_req(cli, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* Unmarshall response */
|
|
||||||
|
|
||||||
if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
result = r.status;
|
|
||||||
|
|
||||||
if (!W_ERROR_IS_OK(result))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
/* copy the data over to the ctr */
|
|
||||||
|
|
||||||
ZERO_STRUCTP(ctr);
|
|
||||||
|
|
||||||
ctr->switch_value = file_level;
|
|
||||||
|
|
||||||
ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
|
|
||||||
|
|
||||||
switch(file_level) {
|
|
||||||
case 3:
|
|
||||||
ctr->file.info3 = (SRV_FILE_INFO_3 *)talloc(
|
|
||||||
mem_ctx, sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
|
|
||||||
|
|
||||||
memset(ctr->file.info3, 0,
|
|
||||||
sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
|
|
||||||
|
|
||||||
for (i = 0; i < r.ctr.num_entries; i++) {
|
|
||||||
SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
/* Copy pointer crap */
|
|
||||||
|
|
||||||
memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3,
|
|
||||||
sizeof(FILE_INFO_3));
|
|
||||||
|
|
||||||
/* Duplicate strings */
|
|
||||||
|
|
||||||
s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
|
|
||||||
if (s)
|
|
||||||
init_unistr2(&info3->info_3_str.uni_path_name, s, 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;
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
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"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
WKS_Q_QUERY_INFO q_o;
|
|
||||||
WKS_R_QUERY_INFO r_o;
|
|
||||||
|
|
||||||
if (cli == NULL || wks100 == NULL)
|
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
|
||||||
|
|
||||||
/* init rpc parse structures */
|
|
||||||
prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
|
|
||||||
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
|
|
||||||
|
|
||||||
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 NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
prs_mem_free(&buf);
|
|
||||||
|
|
||||||
r_o.wks100 = wks100;
|
|
||||||
|
|
||||||
/* get call results from response buffer */
|
|
||||||
if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) {
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 r_o.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do clean up */
|
|
||||||
prs_mem_free(&rbuf);
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
@ -1,546 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unix SMB/CIFS implementation.
|
|
||||||
* MSDfs RPC Pipe client / server routines
|
|
||||||
* Copyright (C) Andrew Tridgell 1992-2000,
|
|
||||||
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
|
|
||||||
* Copyright (C) Shirish Kalele 2000.
|
|
||||||
* Copyright (C) Jeremy Allison 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"
|
|
||||||
#include "nterr.h"
|
|
||||||
#include "rpc_parse.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_PARSE
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Make a DFS_Q_DFS_QUERY structure
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
void init_dfs_q_dfs_exist(DFS_Q_DFS_EXIST *q_d)
|
|
||||||
{
|
|
||||||
q_d->dummy = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Read/write a DFS_Q_DFS_EXIST structure - dummy...
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_q_dfs_exist(const char *desc, DFS_Q_DFS_EXIST *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_q_dfs_exist");
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Read/write a DFS_R_DFS_EXIST structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_r_dfs_exist(const char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_r_dfs_exist");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("exist flag", ps, 0, &q_d->status))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Make a DFS_Q_DFS_REMOVE structure
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
BOOL init_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, const char *entrypath,
|
|
||||||
const char *servername, const char *sharename)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_dfs_q_dfs_remove\n"));
|
|
||||||
init_unistr2(&q_d->DfsEntryPath, entrypath, strlen(entrypath)+1);
|
|
||||||
init_unistr2(&q_d->ServerName, servername, strlen(servername)+1);
|
|
||||||
init_unistr2(&q_d->ShareName, sharename, strlen(sharename)+1);
|
|
||||||
q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Read/write a DFS_Q_DFS_REMOVE structure
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_q_dfs_remove(const char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_q_dfs_remove");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_ServerName", ps, depth, &q_d->ptr_ServerName))
|
|
||||||
return False;
|
|
||||||
if(q_d->ptr_ServerName)
|
|
||||||
if (!smb_io_unistr2("ServerName",&q_d->ServerName, q_d->ptr_ServerName, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
|
|
||||||
return False;
|
|
||||||
if(q_d->ptr_ShareName)
|
|
||||||
if (!smb_io_unistr2("ShareName",&q_d->ShareName, q_d->ptr_ShareName, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Read/write a DFS_R_DFS_REMOVE structure
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_r_dfs_remove(const char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(r_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_r_dfs_remove");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_werror("status", ps, depth, &r_d->status))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Make a DFS_Q_DFS_ADD structure
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
BOOL init_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, const char *entrypath,
|
|
||||||
const char *servername, const char *sharename,
|
|
||||||
const char *comment, uint32 flags)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_dfs_q_dfs_add\n"));
|
|
||||||
q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
|
|
||||||
init_unistr2(&q_d->DfsEntryPath, entrypath, strlen(entrypath)+1);
|
|
||||||
init_unistr2(&q_d->ServerName, servername, strlen(servername)+1);
|
|
||||||
init_unistr2(&q_d->ShareName, sharename, strlen(sharename)+1);
|
|
||||||
if(comment != NULL) {
|
|
||||||
init_unistr2(&q_d->Comment, comment, strlen(comment)+1);
|
|
||||||
q_d->ptr_Comment = 1;
|
|
||||||
} else {
|
|
||||||
q_d->ptr_Comment = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
q_d->Flags = flags;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_Q_DFS_ADD structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_q_dfs_add(const char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_q_dfs_add");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("ServerName",&q_d->ServerName, 1, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("ShareName",&q_d->ShareName, 1, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_Comment", ps, depth, &q_d->ptr_Comment))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("",&q_d->Comment, q_d->ptr_Comment , ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("Flags", ps, depth, &q_d->Flags))
|
|
||||||
return True;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_R_DFS_ADD structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_r_dfs_add(const char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(r_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_r_dfs_add");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_werror("status", ps, depth, &r_d->status))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL init_dfs_q_dfs_get_info(DFS_Q_DFS_GET_INFO *q_d, const char *entrypath,
|
|
||||||
const char *servername, const char *sharename,
|
|
||||||
uint32 info_level)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_dfs_q2_get_info\n"));
|
|
||||||
init_unistr2(&q_d->uni_path, entrypath, strlen(entrypath)+1);
|
|
||||||
init_unistr2(&q_d->uni_server, servername, strlen(servername)+1);
|
|
||||||
init_unistr2(&q_d->uni_share, sharename, strlen(sharename)+1);
|
|
||||||
q_d->level = info_level;
|
|
||||||
q_d->ptr_server = q_d->ptr_share = 1;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_Q_GET_INFO structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_q_dfs_get_info(const char *desc, DFS_Q_DFS_GET_INFO* q_i, prs_struct* ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_i == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_q_dfs_get_info");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("",&q_i->uni_path, 1, ps, depth))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_server", ps, depth, &q_i->ptr_server))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(q_i->ptr_server)
|
|
||||||
if (!smb_io_unistr2("",&q_i->uni_server, q_i->ptr_server, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_share", ps, depth, &q_i->ptr_share))
|
|
||||||
return False;
|
|
||||||
if(q_i->ptr_share)
|
|
||||||
if(!smb_io_unistr2("", &q_i->uni_share, q_i->ptr_share, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("level", ps, depth, &q_i->level))
|
|
||||||
return False;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_R_GET_INFO structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_r_dfs_get_info(const char *desc, DFS_R_DFS_GET_INFO* r_i, prs_struct* ps, int depth)
|
|
||||||
{
|
|
||||||
if(r_i == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("level", ps, depth, &r_i->level))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_ctr", ps, depth, &r_i->ptr_ctr))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!dfs_io_dfs_info_ctr("", &r_i->ctr, 1, r_i->level, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_werror("status", ps, depth, &r_i->status))
|
|
||||||
return False;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Make a DFS_Q_DFS_ENUM structure
|
|
||||||
************************************************************/
|
|
||||||
BOOL init_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr)
|
|
||||||
{
|
|
||||||
q_d->level = level;
|
|
||||||
q_d->maxpreflen = -1;
|
|
||||||
q_d->ptr_buffer = 1;
|
|
||||||
q_d->level2 = level;
|
|
||||||
|
|
||||||
q_d->ptr_num_entries = 1;
|
|
||||||
q_d->num_entries = 0;
|
|
||||||
q_d->num_entries2 = 0;
|
|
||||||
q_d->reshnd.ptr_hnd = 1;
|
|
||||||
q_d->reshnd.handle = 0;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read or write the DFS_Q_DFS_ENUM structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_q_dfs_enum(const char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_q_dfs_enum");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("level", ps, depth, &q_d->level))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("maxpreflen", ps, depth, &q_d->maxpreflen))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("level2", ps, depth, &q_d->level2))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("level3", ps, depth, &q_d->level2))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("num_entries2", ps, depth, &q_d->num_entries2))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_enum_hnd("resume_hnd",&q_d->reshnd, ps, depth))
|
|
||||||
return False;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_INFO_CTR structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_dfs_info_ctr(const char *desc, DFS_INFO_CTR* ctr, uint32 num_entries, uint32 level, prs_struct* ps, int depth)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
switch(level) {
|
|
||||||
case 1:
|
|
||||||
depth++;
|
|
||||||
/* should depend on whether marshalling or unmarshalling! */
|
|
||||||
if(UNMARSHALLING(ps)) {
|
|
||||||
ctr->dfs.info1 = (DFS_INFO_1 *)prs_alloc_mem(ps, sizeof(DFS_INFO_1)*num_entries);
|
|
||||||
if (!ctr->dfs.info1)
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!prs_uint32("ptr_entrypath",ps, depth, &ctr->dfs.info1[i].ptr_entrypath))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!smb_io_unistr2("", &ctr->dfs.info1[i].entrypath, ctr->dfs.info1[i].ptr_entrypath, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
depth--;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
depth++;
|
|
||||||
if(UNMARSHALLING(ps)) {
|
|
||||||
ctr->dfs.info2 = (DFS_INFO_2 *)prs_alloc_mem(ps, num_entries*sizeof(DFS_INFO_2));
|
|
||||||
if (!ctr->dfs.info2)
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info2[i].ptr_entrypath))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info2[i].ptr_comment))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("state", ps, depth, &ctr->dfs.info2[i].state))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info2[i].num_storages))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!smb_io_unistr2("", &ctr->dfs.info2[i].entrypath, ctr->dfs.info2[i].ptr_entrypath, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("",&ctr->dfs.info2[i].comment, ctr->dfs.info2[i].ptr_comment, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
depth--;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
depth++;
|
|
||||||
if(UNMARSHALLING(ps)) {
|
|
||||||
ctr->dfs.info3 = (DFS_INFO_3 *)prs_alloc_mem(ps, num_entries*sizeof(DFS_INFO_3));
|
|
||||||
if (!ctr->dfs.info3)
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info3[i].ptr_entrypath))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info3[i].ptr_comment))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("state", ps, depth, &ctr->dfs.info3[i].state))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info3[i].num_storages))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_storages", ps, depth, &ctr->dfs.info3[i].ptr_storages))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
for(i=0;i<num_entries;i++) {
|
|
||||||
if(!smb_io_unistr2("", &ctr->dfs.info3[i].entrypath, ctr->dfs.info3[i].ptr_entrypath, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("", &ctr->dfs.info3[i].comment, ctr->dfs.info3[i].ptr_comment, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("num_storage_infos", ps, depth, &ctr->dfs.info3[i].num_storage_infos))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!dfs_io_dfs_storage_info("storage_info", &ctr->dfs.info3[i], ps, depth))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
Read/write a DFS_R_DFS_ENUM structure
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
BOOL dfs_io_r_dfs_enum(const char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
DFS_INFO_CTR *ctr;
|
|
||||||
if(q_d == NULL)
|
|
||||||
return False;
|
|
||||||
ctr = q_d->ctr;
|
|
||||||
if(ctr == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("level", ps, depth, &q_d->level))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("level2", ps, depth, &ctr->switch_value))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
|
|
||||||
return False;
|
|
||||||
if(q_d->ptr_num_entries)
|
|
||||||
if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_num_entries2", ps, depth, &q_d->ptr_num_entries2))
|
|
||||||
return False;
|
|
||||||
if(q_d->ptr_num_entries2)
|
|
||||||
if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_enum_hnd("resume_hnd", &q_d->reshnd, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_werror("status", ps, depth, &q_d->status))
|
|
||||||
return False;
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL dfs_io_dfs_storage_info(const char *desc, DFS_INFO_3* info3, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
if(info3 == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "smb_io_dfs_storage_info");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(UNMARSHALLING(ps)) {
|
|
||||||
info3->storages = (DFS_STORAGE_INFO *)prs_alloc_mem(ps, info3->num_storage_infos*sizeof(DFS_STORAGE_INFO));
|
|
||||||
if (!info3->storages)
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<info3->num_storage_infos;i++) {
|
|
||||||
if(!prs_uint32("storage_state", ps, depth, &info3->storages[i].state))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_servername", ps, depth, &info3->storages[i].ptr_servername))
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_sharename", ps, depth, &info3->storages[i].ptr_sharename))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<info3->num_storage_infos;i++) {
|
|
||||||
if(!smb_io_unistr2("servername", &info3->storages[i].servername, info3->storages[i].ptr_servername, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("sharename", &info3->storages[i].sharename, info3->storages[i].ptr_sharename, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unix SMB/CIFS implementation.
|
|
||||||
* RPC Pipe client / server routines
|
|
||||||
* Copyright (C) Gerald Carter 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"
|
|
||||||
|
|
||||||
static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic)
|
|
||||||
{
|
|
||||||
DSROLE_PRIMARY_DOMAIN_INFO_BASIC *p = *basic;
|
|
||||||
|
|
||||||
if ( UNMARSHALLING(ps) )
|
|
||||||
p = *basic = (DSROLE_PRIMARY_DOMAIN_INFO_BASIC *)prs_alloc_mem(ps, sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC));
|
|
||||||
|
|
||||||
if ( !p )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint16("machine_role", ps, depth, &p->machine_role) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_uint16("unknown", ps, depth, &p->unknown) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint32("flags", ps, depth, &p->flags) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint32("netbios_ptr", ps, depth, &p->netbios_ptr) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_uint32("dnsname_ptr", ps, depth, &p->dnsname_ptr) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_uint32("forestname_ptr", ps, depth, &p->forestname_ptr) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint8s(False, "domain_guid", ps, depth, p->domain_guid.info, GUID_SIZE) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !smb_io_unistr2( "netbios_domain", &p->netbios_domain, p->netbios_ptr, ps, depth) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_align(ps) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !smb_io_unistr2( "dns_domain", &p->dns_domain, p->dnsname_ptr, ps, depth) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_align(ps) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !smb_io_unistr2( "forest_domain", &p->forest_domain, p->forestname_ptr, ps, depth) )
|
|
||||||
return False;
|
|
||||||
if ( !prs_align(ps) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
|
|
||||||
return True;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ds_io_q_getprimdominfo( const char *desc, DS_Q_GETPRIMDOMINFO *q_u, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
prs_debug(ps, depth, desc, "ds_io_q_getprimdominfo");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint16( "level", ps, depth, &q_u->level ) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ds_io_r_getprimdominfo( const char *desc, DS_R_GETPRIMDOMINFO *r_u, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
prs_debug(ps, depth, desc, "ds_io_r_getprimdominfo");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint32( "ptr", ps, depth, &r_u->ptr ) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( r_u->ptr )
|
|
||||||
{
|
|
||||||
if ( !prs_uint16( "level", ps, depth, &r_u->level ) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_uint16( "unknown0", ps, depth, &r_u->unknown0 ) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
switch ( r_u->level )
|
|
||||||
{
|
|
||||||
case DsRolePrimaryDomainInfoBasic:
|
|
||||||
if ( !ds_io_dominfobasic( "dominfobasic", ps, depth, &r_u->info.basic ) )
|
|
||||||
return False;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !prs_align(ps) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if ( !prs_ntstatus("status", ps, depth, &r_u->status ) )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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_PARSE
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Init
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
void init_wks_q_query_info(WKS_Q_QUERY_INFO *q_u,
|
|
||||||
char *server, uint16 switch_value)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_wks_q_query_info\n"));
|
|
||||||
|
|
||||||
init_buf_unistr2(&q_u->uni_srv_name, &q_u->ptr_srv_name, server);
|
|
||||||
q_u->switch_value = switch_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Reads or writes a WKS_Q_QUERY_INFO structure.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
BOOL wks_io_q_query_info(const char *desc, WKS_Q_QUERY_INFO *q_u, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if (q_u == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "wks_io_q_query_info");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_srv_name", ps, depth, &q_u->ptr_srv_name))
|
|
||||||
return False;
|
|
||||||
if(!smb_io_unistr2("", &q_u->uni_srv_name, q_u->ptr_srv_name, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint16("switch_value", ps, depth, &q_u->switch_value))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
wks_info_100
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
void init_wks_info_100(WKS_INFO_100 *inf,
|
|
||||||
uint32 platform_id, uint32 ver_major, uint32 ver_minor,
|
|
||||||
char *my_name, char *domain_name)
|
|
||||||
{
|
|
||||||
DEBUG(5,("Init WKS_INFO_100: %d\n", __LINE__));
|
|
||||||
|
|
||||||
inf->platform_id = platform_id; /* 0x0000 01f4 - unknown */
|
|
||||||
inf->ver_major = ver_major; /* os major version */
|
|
||||||
inf->ver_minor = ver_minor; /* os minor version */
|
|
||||||
|
|
||||||
init_buf_unistr2(&inf->uni_compname, &inf->ptr_compname, my_name );
|
|
||||||
init_buf_unistr2(&inf->uni_lan_grp, &inf->ptr_lan_grp, domain_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Reads or writes a WKS_INFO_100 structure.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL wks_io_wks_info_100(const char *desc, WKS_INFO_100 *inf, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if (inf == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "wks_io_wks_info_100");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("platform_id ", ps, depth, &inf->platform_id)) /* 0x0000 01f4 - unknown */
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_compname", ps, depth, &inf->ptr_compname)) /* pointer to computer name */
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ptr_lan_grp ", ps, depth, &inf->ptr_lan_grp)) /* pointer to LAN group name */
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ver_major ", ps, depth, &inf->ver_major)) /* 4 - major os version */
|
|
||||||
return False;
|
|
||||||
if(!prs_uint32("ver_minor ", ps, depth, &inf->ver_minor)) /* 0 - minor os version */
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("", &inf->uni_compname, inf->ptr_compname, ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!smb_io_unistr2("", &inf->uni_lan_grp, inf->ptr_lan_grp , ps, depth))
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Inits WKS_R_QUERY_INFO.
|
|
||||||
|
|
||||||
only supports info level 100 at the moment.
|
|
||||||
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
void init_wks_r_query_info(WKS_R_QUERY_INFO *r_u,
|
|
||||||
uint32 switch_value, WKS_INFO_100 *wks100,
|
|
||||||
NTSTATUS status)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_wks_r_unknown_0: %d\n", __LINE__));
|
|
||||||
|
|
||||||
r_u->switch_value = switch_value; /* same as in request */
|
|
||||||
|
|
||||||
r_u->ptr_1 = 1; /* pointer 1 */
|
|
||||||
r_u->wks100 = wks100;
|
|
||||||
|
|
||||||
r_u->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Reads or writes a structure.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
BOOL wks_io_r_query_info(const char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth)
|
|
||||||
{
|
|
||||||
if (r_u == NULL)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
prs_debug(ps, depth, desc, "wks_io_r_query_info");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint16("switch_value", ps, depth, &r_u->switch_value)) /* level 100 (0x64) */
|
|
||||||
return False;
|
|
||||||
if(!prs_align(ps))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_uint32("ptr_1 ", ps, depth, &r_u->ptr_1)) /* pointer 1 */
|
|
||||||
return False;
|
|
||||||
if(!wks_io_wks_info_100("inf", r_u->wks100, ps, depth))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
if(!prs_ntstatus("status ", ps, depth, &r_u->status))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
@ -1,177 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unix SMB/CIFS implementation.
|
|
||||||
* RPC Pipe client / server routines for Dfs
|
|
||||||
* Copyright (C) Andrew Tridgell 1992-1997,
|
|
||||||
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
|
|
||||||
* Copyright (C) Shirish Kalele 2000,
|
|
||||||
* Copyright (C) Jeremy Allison 2001,
|
|
||||||
* Copyright (C) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface to the dfs pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "nterr.h"
|
|
||||||
|
|
||||||
#define MAX_MSDFS_JUNCTIONS 256
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/**********************************************************************
|
|
||||||
api_dfs_exist
|
|
||||||
**********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_dfs_exist(pipes_struct *p)
|
|
||||||
{
|
|
||||||
DFS_Q_DFS_EXIST q_u;
|
|
||||||
DFS_R_DFS_EXIST r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
if(!dfs_io_q_dfs_exist("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _dfs_exist(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_exist("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************
|
|
||||||
api_dfs_add
|
|
||||||
*****************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_dfs_add(pipes_struct *p)
|
|
||||||
{
|
|
||||||
DFS_Q_DFS_ADD q_u;
|
|
||||||
DFS_R_DFS_ADD r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_q_dfs_add("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _dfs_add(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_add("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************
|
|
||||||
api_dfs_remove
|
|
||||||
*****************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_dfs_remove(pipes_struct *p)
|
|
||||||
{
|
|
||||||
DFS_Q_DFS_REMOVE q_u;
|
|
||||||
DFS_R_DFS_REMOVE r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_q_dfs_remove("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _dfs_remove(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!dfs_io_r_dfs_remove("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_dfs_get_info
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_dfs_get_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
DFS_Q_DFS_GET_INFO q_u;
|
|
||||||
DFS_R_DFS_GET_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_q_dfs_get_info("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _dfs_get_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_r_dfs_get_info("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_dfs_enum
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_dfs_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
DFS_Q_DFS_ENUM q_u;
|
|
||||||
DFS_R_DFS_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_q_dfs_enum("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _dfs_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!dfs_io_r_dfs_enum("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
\pipe\netdfs commands
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_DFS_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_dfs_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct api_struct api_netdfs_cmds[] =
|
|
||||||
{
|
|
||||||
{"DFS_EXIST", DFS_EXIST, api_dfs_exist },
|
|
||||||
{"DFS_ADD", DFS_ADD, api_dfs_add },
|
|
||||||
{"DFS_REMOVE", DFS_REMOVE, api_dfs_remove },
|
|
||||||
{"DFS_GET_INFO", DFS_GET_INFO, api_dfs_get_info },
|
|
||||||
{"DFS_ENUM", DFS_ENUM, api_dfs_enum }
|
|
||||||
};
|
|
||||||
return rpc_pipe_register_commands("netdfs", "netdfs", api_netdfs_cmds,
|
|
||||||
sizeof(api_netdfs_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
@ -1,371 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unix SMB/CIFS implementation.
|
|
||||||
* RPC Pipe client / server routines for Dfs
|
|
||||||
* Copyright (C) Andrew Tridgell 1992-1997,
|
|
||||||
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
|
|
||||||
* Copyright (C) Shirish Kalele 2000.
|
|
||||||
* Copyright (C) Jeremy Allison 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the implementation of the dfs pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
#include "nterr.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
#define MAX_MSDFS_JUNCTIONS 256
|
|
||||||
|
|
||||||
/* This function does not return a WERROR or NTSTATUS code but rather 1 if
|
|
||||||
dfs exists, or 0 otherwise. */
|
|
||||||
|
|
||||||
uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u)
|
|
||||||
{
|
|
||||||
if(lp_host_msdfs())
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
|
|
||||||
{
|
|
||||||
struct current_user user;
|
|
||||||
struct junction_map jn;
|
|
||||||
struct referral* old_referral_list = NULL;
|
|
||||||
BOOL exists = False;
|
|
||||||
|
|
||||||
pstring dfspath, servername, sharename;
|
|
||||||
pstring altpath;
|
|
||||||
|
|
||||||
get_current_user(&user,p);
|
|
||||||
|
|
||||||
if (user.uid != 0) {
|
|
||||||
DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));
|
|
||||||
return WERR_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
|
|
||||||
unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
|
|
||||||
unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
|
|
||||||
|
|
||||||
DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
|
|
||||||
dfspath, servername, sharename));
|
|
||||||
|
|
||||||
pstrcpy(altpath, servername);
|
|
||||||
pstrcat(altpath, "\\");
|
|
||||||
pstrcat(altpath, sharename);
|
|
||||||
|
|
||||||
if(get_referred_path(dfspath, &jn, NULL, NULL))
|
|
||||||
{
|
|
||||||
exists = True;
|
|
||||||
jn.referral_count += 1;
|
|
||||||
old_referral_list = jn.referral_list;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
jn.referral_count = 1;
|
|
||||||
|
|
||||||
jn.referral_list = (struct referral*) talloc(p->mem_ctx, jn.referral_count
|
|
||||||
* sizeof(struct referral));
|
|
||||||
|
|
||||||
if(jn.referral_list == NULL)
|
|
||||||
{
|
|
||||||
DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n"));
|
|
||||||
return WERR_DFS_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(old_referral_list)
|
|
||||||
{
|
|
||||||
memcpy(jn.referral_list, old_referral_list,
|
|
||||||
sizeof(struct referral)*jn.referral_count-1);
|
|
||||||
SAFE_FREE(old_referral_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
jn.referral_list[jn.referral_count-1].proximity = 0;
|
|
||||||
jn.referral_list[jn.referral_count-1].ttl = REFERRAL_TTL;
|
|
||||||
|
|
||||||
pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath);
|
|
||||||
|
|
||||||
if(!create_msdfs_link(&jn, exists))
|
|
||||||
return WERR_DFS_CANT_CREATE_JUNCT;
|
|
||||||
|
|
||||||
return WERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
|
|
||||||
DFS_R_DFS_REMOVE *r_u)
|
|
||||||
{
|
|
||||||
struct current_user user;
|
|
||||||
struct junction_map jn;
|
|
||||||
BOOL found = False;
|
|
||||||
|
|
||||||
pstring dfspath, servername, sharename;
|
|
||||||
pstring altpath;
|
|
||||||
|
|
||||||
get_current_user(&user,p);
|
|
||||||
|
|
||||||
if (user.uid != 0) {
|
|
||||||
DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));
|
|
||||||
return WERR_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
|
|
||||||
if(q_u->ptr_ServerName)
|
|
||||||
unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
|
|
||||||
|
|
||||||
if(q_u->ptr_ShareName)
|
|
||||||
unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
|
|
||||||
|
|
||||||
if(q_u->ptr_ServerName && q_u->ptr_ShareName)
|
|
||||||
{
|
|
||||||
pstrcpy(altpath, servername);
|
|
||||||
pstrcat(altpath, "\\");
|
|
||||||
pstrcat(altpath, sharename);
|
|
||||||
strlower(altpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
|
|
||||||
dfspath, servername, sharename));
|
|
||||||
|
|
||||||
if(!get_referred_path(dfspath, &jn, NULL, NULL))
|
|
||||||
return WERR_DFS_NO_SUCH_VOL;
|
|
||||||
|
|
||||||
/* if no server-share pair given, remove the msdfs link completely */
|
|
||||||
if(!q_u->ptr_ServerName && !q_u->ptr_ShareName)
|
|
||||||
{
|
|
||||||
if(!remove_msdfs_link(&jn))
|
|
||||||
return WERR_DFS_NO_SUCH_VOL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
/* compare each referral in the list with the one to remove */
|
|
||||||
DEBUG(10,("altpath: .%s. refcnt: %d\n", altpath, jn.referral_count));
|
|
||||||
for(i=0;i<jn.referral_count;i++)
|
|
||||||
{
|
|
||||||
pstring refpath;
|
|
||||||
pstrcpy(refpath,jn.referral_list[i].alternate_path);
|
|
||||||
trim_string(refpath, "\\", "\\");
|
|
||||||
DEBUG(10,("_dfs_remove: refpath: .%s.\n", refpath));
|
|
||||||
if(strequal(refpath, altpath))
|
|
||||||
{
|
|
||||||
*(jn.referral_list[i].alternate_path)='\0';
|
|
||||||
DEBUG(10,("_dfs_remove: Removal request matches referral %s\n",
|
|
||||||
refpath));
|
|
||||||
found = True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!found)
|
|
||||||
return WERR_DFS_NO_SUCH_SHARE;
|
|
||||||
|
|
||||||
/* Only one referral, remove it */
|
|
||||||
if(jn.referral_count == 1)
|
|
||||||
{
|
|
||||||
if(!remove_msdfs_link(&jn))
|
|
||||||
return WERR_DFS_NO_SUCH_VOL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!create_msdfs_link(&jn, True))
|
|
||||||
return WERR_DFS_CANT_CREATE_JUNCT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return WERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL init_reply_dfs_info_1(struct junction_map* j, DFS_INFO_1* dfs1, int num_j)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
for(i=0;i<num_j;i++)
|
|
||||||
{
|
|
||||||
pstring str;
|
|
||||||
dfs1[i].ptr_entrypath = 1;
|
|
||||||
slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", lp_netbios_name(),
|
|
||||||
j[i].service_name, j[i].volume_name);
|
|
||||||
DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i,str));
|
|
||||||
init_unistr2(&dfs1[i].entrypath,str,strlen(str)+1);
|
|
||||||
}
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL init_reply_dfs_info_2(struct junction_map* j, DFS_INFO_2* dfs2, int num_j)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
for(i=0;i<num_j;i++)
|
|
||||||
{
|
|
||||||
pstring str;
|
|
||||||
dfs2[i].ptr_entrypath = 1;
|
|
||||||
slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", lp_netbios_name(),
|
|
||||||
j[i].service_name, j[i].volume_name);
|
|
||||||
init_unistr2(&dfs2[i].entrypath, str, strlen(str)+1);
|
|
||||||
dfs2[i].ptr_comment = 0;
|
|
||||||
dfs2[i].state = 1; /* set up state of dfs junction as OK */
|
|
||||||
dfs2[i].num_storages = j[i].referral_count;
|
|
||||||
}
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_INFO_3* dfs3, int num_j)
|
|
||||||
{
|
|
||||||
int i=0,ii=0;
|
|
||||||
for(i=0;i<num_j;i++)
|
|
||||||
{
|
|
||||||
pstring str;
|
|
||||||
dfs3[i].ptr_entrypath = 1;
|
|
||||||
if (j[i].volume_name[0] == '\0')
|
|
||||||
slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
|
|
||||||
lp_netbios_name(), j[i].service_name);
|
|
||||||
else
|
|
||||||
slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", lp_netbios_name(),
|
|
||||||
j[i].service_name, j[i].volume_name);
|
|
||||||
|
|
||||||
init_unistr2(&dfs3[i].entrypath, str, strlen(str)+1);
|
|
||||||
dfs3[i].ptr_comment = 1;
|
|
||||||
init_unistr2(&dfs3[i].comment, "", 1);
|
|
||||||
dfs3[i].state = 1;
|
|
||||||
dfs3[i].num_storages = dfs3[i].num_storage_infos = j[i].referral_count;
|
|
||||||
dfs3[i].ptr_storages = 1;
|
|
||||||
|
|
||||||
/* also enumerate the storages */
|
|
||||||
dfs3[i].storages = (DFS_STORAGE_INFO*) talloc(ctx, j[i].referral_count *
|
|
||||||
sizeof(DFS_STORAGE_INFO));
|
|
||||||
if (!dfs3[i].storages)
|
|
||||||
return False;
|
|
||||||
|
|
||||||
memset(dfs3[i].storages, '\0', j[i].referral_count * sizeof(DFS_STORAGE_INFO));
|
|
||||||
|
|
||||||
for(ii=0;ii<j[i].referral_count;ii++)
|
|
||||||
{
|
|
||||||
char* p;
|
|
||||||
pstring path;
|
|
||||||
DFS_STORAGE_INFO* stor = &(dfs3[i].storages[ii]);
|
|
||||||
struct referral* ref = &(j[i].referral_list[ii]);
|
|
||||||
|
|
||||||
pstrcpy(path, ref->alternate_path);
|
|
||||||
trim_string(path,"\\","");
|
|
||||||
p = strrchr_m(path,'\\');
|
|
||||||
if(p==NULL)
|
|
||||||
{
|
|
||||||
DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*p = '\0';
|
|
||||||
DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1));
|
|
||||||
stor->state = 2; /* set all storages as ONLINE */
|
|
||||||
init_unistr2(&stor->servername, path, strlen(path)+1);
|
|
||||||
init_unistr2(&stor->sharename, p+1, strlen(p+1)+1);
|
|
||||||
stor->ptr_servername = stor->ptr_sharename = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
static WERROR init_reply_dfs_ctr(TALLOC_CTX *ctx, uint32 level,
|
|
||||||
DFS_INFO_CTR* ctr, struct junction_map* jn,
|
|
||||||
int num_jn)
|
|
||||||
{
|
|
||||||
/* do the levels */
|
|
||||||
switch(level)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
DFS_INFO_1* dfs1;
|
|
||||||
dfs1 = (DFS_INFO_1*) talloc(ctx, num_jn * sizeof(DFS_INFO_1));
|
|
||||||
if (!dfs1)
|
|
||||||
return WERR_NOMEM;
|
|
||||||
init_reply_dfs_info_1(jn, dfs1, num_jn);
|
|
||||||
ctr->dfs.info1 = dfs1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
DFS_INFO_2* dfs2;
|
|
||||||
dfs2 = (DFS_INFO_2*) talloc(ctx, num_jn * sizeof(DFS_INFO_2));
|
|
||||||
if (!dfs2)
|
|
||||||
return WERR_NOMEM;
|
|
||||||
init_reply_dfs_info_2(jn, dfs2, num_jn);
|
|
||||||
ctr->dfs.info2 = dfs2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
DFS_INFO_3* dfs3;
|
|
||||||
dfs3 = (DFS_INFO_3*) talloc(ctx, num_jn * sizeof(DFS_INFO_3));
|
|
||||||
if (!dfs3)
|
|
||||||
return WERR_NOMEM;
|
|
||||||
init_reply_dfs_info_3(ctx, jn, dfs3, num_jn);
|
|
||||||
ctr->dfs.info3 = dfs3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return WERR_INVALID_PARAM;
|
|
||||||
}
|
|
||||||
return WERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u)
|
|
||||||
{
|
|
||||||
uint32 level = q_u->level;
|
|
||||||
struct junction_map jn[MAX_MSDFS_JUNCTIONS];
|
|
||||||
int num_jn = 0;
|
|
||||||
|
|
||||||
num_jn = enum_msdfs_links(jn);
|
|
||||||
|
|
||||||
DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
|
|
||||||
|
|
||||||
r_u->ptr_buffer = level;
|
|
||||||
r_u->level = r_u->level2 = level;
|
|
||||||
r_u->ptr_num_entries = r_u->ptr_num_entries2 = 1;
|
|
||||||
r_u->num_entries = r_u->num_entries2 = num_jn;
|
|
||||||
r_u->reshnd.ptr_hnd = 1;
|
|
||||||
r_u->reshnd.handle = num_jn;
|
|
||||||
|
|
||||||
r_u->ctr = (DFS_INFO_CTR*)talloc(p->mem_ctx, sizeof(DFS_INFO_CTR));
|
|
||||||
if (!r_u->ctr)
|
|
||||||
return WERR_NOMEM;
|
|
||||||
ZERO_STRUCTP(r_u->ctr);
|
|
||||||
r_u->ctr->switch_value = level;
|
|
||||||
r_u->ctr->num_entries = num_jn;
|
|
||||||
r_u->ctr->ptr_dfs_ctr = 1;
|
|
||||||
|
|
||||||
r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, r_u->ctr, jn, num_jn);
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
|
|
||||||
DFS_R_DFS_GET_INFO *r_u)
|
|
||||||
{
|
|
||||||
UNISTR2* uni_path = &q_u->uni_path;
|
|
||||||
uint32 level = q_u->level;
|
|
||||||
pstring path;
|
|
||||||
struct junction_map jn;
|
|
||||||
|
|
||||||
unistr2_to_ascii(path, uni_path, sizeof(path)-1);
|
|
||||||
if(!create_junction(path, &jn))
|
|
||||||
return WERR_DFS_NO_SUCH_SERVER;
|
|
||||||
|
|
||||||
if(!get_referred_path(path, &jn, NULL, NULL))
|
|
||||||
return WERR_DFS_NO_SUCH_VOL;
|
|
||||||
|
|
||||||
r_u->level = level;
|
|
||||||
r_u->ptr_ctr = 1;
|
|
||||||
r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, &r_u->ctr, &jn, 1);
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
@ -1,810 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 2001,
|
|
||||||
* Copyright (C) Jim McDonough 2002,
|
|
||||||
* Copyright (C) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface to the lsa server code. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_policy2
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_open_policy2(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_OPEN_POL2 q_u;
|
|
||||||
LSA_R_OPEN_POL2 r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the server, object attributes and desired access flag...*/
|
|
||||||
if(!lsa_io_q_open_pol2("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_policy2: unable to unmarshall LSA_Q_OPEN_POL2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_open_policy2(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_open_pol2("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_policy2: unable to marshall LSA_R_OPEN_POL2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_policy
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_open_policy(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_OPEN_POL q_u;
|
|
||||||
LSA_R_OPEN_POL r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the server, object attributes and desired access flag...*/
|
|
||||||
if(!lsa_io_q_open_pol("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_policy: unable to unmarshall LSA_Q_OPEN_POL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_open_policy(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_open_pol("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_policy: unable to marshall LSA_R_OPEN_POL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_enum_trust_dom
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_enum_trust_dom(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUM_TRUST_DOM q_u;
|
|
||||||
LSA_R_ENUM_TRUST_DOM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the enum trust domain context etc. */
|
|
||||||
if(!lsa_io_q_enum_trust_dom("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* get required trusted domains information */
|
|
||||||
r_u.status = _lsa_enum_trust_dom(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* prepare the response */
|
|
||||||
if(!lsa_io_r_enum_trust_dom("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_query_info
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_query_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_QUERY_INFO q_u;
|
|
||||||
LSA_R_QUERY_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the info class and policy handle */
|
|
||||||
if(!lsa_io_q_query("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_info: failed to unmarshall LSA_Q_QUERY_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_query_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_query("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_info: failed to marshall LSA_R_QUERY_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_lookup_sids
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_lookup_sids(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_LOOKUP_SIDS q_u;
|
|
||||||
LSA_R_LOOKUP_SIDS r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the info class and policy handle */
|
|
||||||
if(!lsa_io_q_lookup_sids("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_lookup_sids: failed to unmarshall LSA_Q_LOOKUP_SIDS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_lookup_sids(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_r_lookup_sids("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_lookup_sids: Failed to marshall LSA_R_LOOKUP_SIDS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_lookup_names
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_lookup_names(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_LOOKUP_NAMES q_u;
|
|
||||||
LSA_R_LOOKUP_NAMES r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the info class and policy handle */
|
|
||||||
if(!lsa_io_q_lookup_names("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_lookup_names: failed to unmarshall LSA_Q_LOOKUP_NAMES.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_lookup_names(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_lookup_names("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_lookup_names: Failed to marshall LSA_R_LOOKUP_NAMES.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_close.
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_close(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_CLOSE q_u;
|
|
||||||
LSA_R_CLOSE r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if (!lsa_io_q_close("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_close: lsa_io_q_close failed.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_close(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if (!lsa_io_r_close("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_close: lsa_io_r_close failed.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_secret.
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_open_secret(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_OPEN_SECRET q_u;
|
|
||||||
LSA_R_OPEN_SECRET r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_open_secret("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_secret: failed to unmarshall LSA_Q_OPEN_SECRET.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_open_secret(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_open_secret("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_secret: Failed to marshall LSA_R_OPEN_SECRET.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_secret.
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_enum_privs(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUM_PRIVS q_u;
|
|
||||||
LSA_R_ENUM_PRIVS r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_enum_privs("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_privs: failed to unmarshall LSA_Q_ENUM_PRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_enum_privs(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_enum_privs("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_privs: Failed to marshall LSA_R_ENUM_PRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_secret.
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_priv_get_dispname(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_PRIV_GET_DISPNAME q_u;
|
|
||||||
LSA_R_PRIV_GET_DISPNAME r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_priv_get_dispname("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_priv_get_dispname: failed to unmarshall LSA_Q_PRIV_GET_DISPNAME.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_priv_get_dispname(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_priv_get_dispname("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_priv_get_dispname: Failed to marshall LSA_R_PRIV_GET_DISPNAME.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_secret.
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_enum_accounts(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUM_ACCOUNTS q_u;
|
|
||||||
LSA_R_ENUM_ACCOUNTS r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_enum_accounts("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_accounts: failed to unmarshall LSA_Q_ENUM_ACCOUNTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_enum_accounts(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_enum_accounts("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_accounts: Failed to marshall LSA_R_ENUM_ACCOUNTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_UNK_GET_CONNUSER
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_unk_get_connuser(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_UNK_GET_CONNUSER q_u;
|
|
||||||
LSA_R_UNK_GET_CONNUSER r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_unk_get_connuser("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_unk_get_connuser: failed to unmarshall LSA_Q_UNK_GET_CONNUSER.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_unk_get_connuser(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_unk_get_connuser("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_unk_get_connuser: Failed to marshall LSA_R_UNK_GET_CONNUSER.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_open_user
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_open_account(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_OPENACCOUNT q_u;
|
|
||||||
LSA_R_OPENACCOUNT r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_open_account("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_account: failed to unmarshall LSA_Q_OPENACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_open_account(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_open_account("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_open_account: Failed to marshall LSA_R_OPENACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_get_privs
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_enum_privsaccount(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUMPRIVSACCOUNT q_u;
|
|
||||||
LSA_R_ENUMPRIVSACCOUNT r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_enum_privsaccount("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_privsaccount: failed to unmarshall LSA_Q_ENUMPRIVSACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_enum_privsaccount(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_enum_privsaccount("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_privsaccount: Failed to marshall LSA_R_ENUMPRIVSACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_getsystemaccount
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_getsystemaccount(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_GETSYSTEMACCOUNT q_u;
|
|
||||||
LSA_R_GETSYSTEMACCOUNT r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_getsystemaccount("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_getsystemaccount: failed to unmarshall LSA_Q_GETSYSTEMACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_getsystemaccount(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_getsystemaccount("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_getsystemaccount: Failed to marshall LSA_R_GETSYSTEMACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_setsystemaccount
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_setsystemaccount(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_SETSYSTEMACCOUNT q_u;
|
|
||||||
LSA_R_SETSYSTEMACCOUNT r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_setsystemaccount("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_setsystemaccount: failed to unmarshall LSA_Q_SETSYSTEMACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_setsystemaccount(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_setsystemaccount("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_setsystemaccount: Failed to marshall LSA_R_SETSYSTEMACCOUNT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_addprivs
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_addprivs(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ADDPRIVS q_u;
|
|
||||||
LSA_R_ADDPRIVS r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_addprivs("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_addprivs: failed to unmarshall LSA_Q_ADDPRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_addprivs(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_addprivs("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_addprivs: Failed to marshall LSA_R_ADDPRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_removeprivs
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_removeprivs(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_REMOVEPRIVS q_u;
|
|
||||||
LSA_R_REMOVEPRIVS r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_removeprivs("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_removeprivs: failed to unmarshall LSA_Q_REMOVEPRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_removeprivs(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_removeprivs("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_removeprivs: Failed to marshall LSA_R_REMOVEPRIVS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_query_secobj
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_query_secobj(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_QUERY_SEC_OBJ q_u;
|
|
||||||
LSA_R_QUERY_SEC_OBJ r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_query_sec_obj("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_secobj: failed to unmarshall LSA_Q_QUERY_SEC_OBJ.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_query_secobj(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_query_sec_obj("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_secobj: Failed to marshall LSA_R_QUERY_SEC_OBJ.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_query_dnsdomainfo
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_lsa_query_info2(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_QUERY_INFO2 q_u;
|
|
||||||
LSA_R_QUERY_INFO2 r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_query_info2("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_info2: failed to unmarshall LSA_Q_QUERY_INFO2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_query_info2(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!lsa_io_r_query_info2("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_query_info2: failed to marshall LSA_R_QUERY_INFO2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_enum_acctrights
|
|
||||||
***************************************************************************/
|
|
||||||
static BOOL api_lsa_enum_acct_rights(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUM_ACCT_RIGHTS q_u;
|
|
||||||
LSA_R_ENUM_ACCT_RIGHTS r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_enum_acct_rights("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_acct_rights: failed to unmarshall LSA_Q_ENUM_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_enum_acct_rights(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_enum_acct_rights("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_acct_rights: Failed to marshall LSA_R_ENUM_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_enum_acct_with_right
|
|
||||||
***************************************************************************/
|
|
||||||
static BOOL api_lsa_enum_acct_with_right(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ENUM_ACCT_WITH_RIGHT q_u;
|
|
||||||
LSA_R_ENUM_ACCT_WITH_RIGHT r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_enum_acct_with_right("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_acct_with_right: failed to unmarshall LSA_Q_ENUM_ACCT_WITH_RIGHT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_enum_acct_with_right(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_enum_acct_with_right("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_enum_acct_with_right: Failed to marshall LSA_R_ENUM_ACCT_WITH_RIGHT.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_add_acctrights
|
|
||||||
***************************************************************************/
|
|
||||||
static BOOL api_lsa_add_acct_rights(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_ADD_ACCT_RIGHTS q_u;
|
|
||||||
LSA_R_ADD_ACCT_RIGHTS r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_add_acct_rights("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_add_acct_rights: failed to unmarshall LSA_Q_ADD_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_add_acct_rights(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_add_acct_rights("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_add_acct_rights: Failed to marshall LSA_R_ADD_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
api_lsa_remove_acctrights
|
|
||||||
***************************************************************************/
|
|
||||||
static BOOL api_lsa_remove_acct_rights(pipes_struct *p)
|
|
||||||
{
|
|
||||||
LSA_Q_REMOVE_ACCT_RIGHTS q_u;
|
|
||||||
LSA_R_REMOVE_ACCT_RIGHTS r_u;
|
|
||||||
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!lsa_io_q_remove_acct_rights("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_remove_acct_rights: failed to unmarshall LSA_Q_REMOVE_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _lsa_remove_acct_rights(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!lsa_io_r_remove_acct_rights("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_lsa_remove_acct_rights: Failed to marshall LSA_R_REMOVE_ACCT_RIGHTS.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
\PIPE\ntlsa commands
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_LSA_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_lsa_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static const struct api_struct api_lsa_cmds[] =
|
|
||||||
{
|
|
||||||
{ "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 },
|
|
||||||
{ "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy },
|
|
||||||
{ "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info },
|
|
||||||
{ "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom },
|
|
||||||
{ "LSA_CLOSE" , LSA_CLOSE , api_lsa_close },
|
|
||||||
{ "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret },
|
|
||||||
{ "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids },
|
|
||||||
{ "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names },
|
|
||||||
{ "LSA_ENUM_PRIVS" , LSA_ENUM_PRIVS , api_lsa_enum_privs },
|
|
||||||
{ "LSA_PRIV_GET_DISPNAME",LSA_PRIV_GET_DISPNAME,api_lsa_priv_get_dispname},
|
|
||||||
{ "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts },
|
|
||||||
{ "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser },
|
|
||||||
{ "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account },
|
|
||||||
{ "LSA_ENUMPRIVSACCOUNT", LSA_ENUMPRIVSACCOUNT, api_lsa_enum_privsaccount},
|
|
||||||
{ "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount },
|
|
||||||
{ "LSA_SETSYSTEMACCOUNT", LSA_SETSYSTEMACCOUNT, api_lsa_setsystemaccount },
|
|
||||||
{ "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs },
|
|
||||||
{ "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs },
|
|
||||||
{ "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj },
|
|
||||||
{ "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 },
|
|
||||||
{ "LSA_ENUMACCTRIGHTS" , LSA_ENUMACCTRIGHTS , api_lsa_enum_acct_rights },
|
|
||||||
{ "LSA_ENUMACCTWITHRIGHT", LSA_ENUMACCTWITHRIGHT, api_lsa_enum_acct_with_right },
|
|
||||||
{ "LSA_ADDACCTRIGHTS" , LSA_ADDACCTRIGHTS , api_lsa_add_acct_rights },
|
|
||||||
{ "LSA_REMOVEACCTRIGHTS", LSA_REMOVEACCTRIGHTS, api_lsa_remove_acct_rights},
|
|
||||||
};
|
|
||||||
|
|
||||||
return rpc_pipe_register_commands("lsarpc", "lsass", api_lsa_cmds,
|
|
||||||
sizeof(api_lsa_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
@ -1,265 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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) Jeremy Allison 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_SRV
|
|
||||||
|
|
||||||
/* This is the max handles across all instances of a pipe name. */
|
|
||||||
#ifndef MAX_OPEN_POLS
|
|
||||||
#define MAX_OPEN_POLS 1024
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Hack as handles need to be persisant over lsa pipe closes so long as a samr
|
|
||||||
pipe is open. JRA.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static BOOL is_samr_lsa_pipe(const char *pipe_name)
|
|
||||||
{
|
|
||||||
return (strstr(pipe_name, "samr") || strstr(pipe_name, "lsa"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Initialise a policy handle list on a pipe. Handle list is shared between all
|
|
||||||
pipes of the same name.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
BOOL init_pipe_handle_list(pipes_struct *p, char *pipe_name)
|
|
||||||
{
|
|
||||||
pipes_struct *plist = get_first_internal_pipe();
|
|
||||||
struct handle_list *hl = NULL;
|
|
||||||
|
|
||||||
for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) {
|
|
||||||
if (strequal( plist->name, pipe_name) ||
|
|
||||||
(is_samr_lsa_pipe(plist->name) && is_samr_lsa_pipe(pipe_name))) {
|
|
||||||
if (!plist->pipe_handles) {
|
|
||||||
pstring msg;
|
|
||||||
slprintf(msg, sizeof(msg)-1, "init_pipe_handles: NULL pipe_handle pointer in pipe %s",
|
|
||||||
pipe_name );
|
|
||||||
smb_panic(msg);
|
|
||||||
}
|
|
||||||
hl = plist->pipe_handles;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hl) {
|
|
||||||
/*
|
|
||||||
* No handle list for this pipe (first open of pipe).
|
|
||||||
* Create list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((hl = (struct handle_list *)malloc(sizeof(struct handle_list))) == NULL)
|
|
||||||
return False;
|
|
||||||
ZERO_STRUCTP(hl);
|
|
||||||
|
|
||||||
DEBUG(10,("init_pipe_handles: created handle list for pipe %s\n", pipe_name ));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* One more pipe is using this list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hl->pipe_ref_count++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Point this pipe at this list.
|
|
||||||
*/
|
|
||||||
|
|
||||||
p->pipe_handles = hl;
|
|
||||||
|
|
||||||
DEBUG(10,("init_pipe_handles: pipe_handles ref count = %u for pipe %s\n",
|
|
||||||
p->pipe_handles->pipe_ref_count, pipe_name ));
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
find first available policy slot. creates a policy handle for you.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *), void *data_ptr)
|
|
||||||
{
|
|
||||||
static uint32 pol_hnd_low = 0;
|
|
||||||
static uint32 pol_hnd_high = 0;
|
|
||||||
|
|
||||||
struct policy *pol;
|
|
||||||
|
|
||||||
if (p->pipe_handles->count > MAX_OPEN_POLS) {
|
|
||||||
DEBUG(0,("create_policy_hnd: ERROR: too many handles (%d) on this pipe.\n",
|
|
||||||
(int)p->pipe_handles->count));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
pol = (struct policy *)malloc(sizeof(*p));
|
|
||||||
if (!pol) {
|
|
||||||
DEBUG(0,("create_policy_hnd: ERROR: out of memory!\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZERO_STRUCTP(pol);
|
|
||||||
|
|
||||||
pol->data_ptr = data_ptr;
|
|
||||||
pol->free_fn = free_fn;
|
|
||||||
|
|
||||||
pol_hnd_low++;
|
|
||||||
if (pol_hnd_low == 0)
|
|
||||||
(pol_hnd_high)++;
|
|
||||||
|
|
||||||
SIVAL(&pol->pol_hnd.data1, 0 , 0); /* first bit must be null */
|
|
||||||
SIVAL(&pol->pol_hnd.data2, 0 , pol_hnd_low ); /* second bit is incrementing */
|
|
||||||
SSVAL(&pol->pol_hnd.data3, 0 , pol_hnd_high); /* second bit is incrementing */
|
|
||||||
SSVAL(&pol->pol_hnd.data4, 0 , (pol_hnd_high>>16)); /* second bit is incrementing */
|
|
||||||
SIVAL(pol->pol_hnd.data5, 0, time(NULL)); /* something random */
|
|
||||||
SIVAL(pol->pol_hnd.data5, 4, sys_getpid()); /* something more random */
|
|
||||||
|
|
||||||
DLIST_ADD(p->pipe_handles->Policy, pol);
|
|
||||||
p->pipe_handles->count++;
|
|
||||||
|
|
||||||
*hnd = pol->pol_hnd;
|
|
||||||
|
|
||||||
DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
|
|
||||||
dump_data(4, (char *)hnd, sizeof(*hnd));
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
find policy by handle - internal version.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
static struct policy *find_policy_by_hnd_internal(pipes_struct *p, POLICY_HND *hnd, void **data_p)
|
|
||||||
{
|
|
||||||
struct policy *pol;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (data_p)
|
|
||||||
*data_p = NULL;
|
|
||||||
|
|
||||||
for (i = 0, pol=p->pipe_handles->Policy;pol;pol=pol->next, i++) {
|
|
||||||
if (memcmp(&pol->pol_hnd, hnd, sizeof(*hnd)) == 0) {
|
|
||||||
DEBUG(4,("Found policy hnd[%d] ", (int)i));
|
|
||||||
dump_data(4, (char *)hnd, sizeof(*hnd));
|
|
||||||
if (data_p)
|
|
||||||
*data_p = pol->data_ptr;
|
|
||||||
return pol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(4,("Policy not found: "));
|
|
||||||
dump_data(4, (char *)hnd, sizeof(*hnd));
|
|
||||||
|
|
||||||
p->bad_handle_fault_state = True;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
find policy by handle
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
BOOL find_policy_by_hnd(pipes_struct *p, POLICY_HND *hnd, void **data_p)
|
|
||||||
{
|
|
||||||
return find_policy_by_hnd_internal(p, hnd, data_p) == NULL ? False : True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Close a policy.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
|
|
||||||
{
|
|
||||||
struct policy *pol = find_policy_by_hnd_internal(p, hnd, NULL);
|
|
||||||
|
|
||||||
if (!pol) {
|
|
||||||
DEBUG(3,("Error closing policy\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(3,("Closed policy\n"));
|
|
||||||
|
|
||||||
if (pol->free_fn && pol->data_ptr)
|
|
||||||
(*pol->free_fn)(pol->data_ptr);
|
|
||||||
|
|
||||||
p->pipe_handles->count--;
|
|
||||||
|
|
||||||
DLIST_REMOVE(p->pipe_handles->Policy, pol);
|
|
||||||
|
|
||||||
ZERO_STRUCTP(pol);
|
|
||||||
|
|
||||||
SAFE_FREE(pol);
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Close a pipe - free the handle list if it was the last pipe reference.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void close_policy_by_pipe(pipes_struct *p)
|
|
||||||
{
|
|
||||||
p->pipe_handles->pipe_ref_count--;
|
|
||||||
|
|
||||||
if (p->pipe_handles->pipe_ref_count == 0) {
|
|
||||||
/*
|
|
||||||
* Last pipe open on this list - free the list.
|
|
||||||
*/
|
|
||||||
while (p->pipe_handles->Policy)
|
|
||||||
close_policy_hnd(p, &p->pipe_handles->Policy->pol_hnd);
|
|
||||||
|
|
||||||
p->pipe_handles->Policy = NULL;
|
|
||||||
p->pipe_handles->count = 0;
|
|
||||||
|
|
||||||
SAFE_FREE(p->pipe_handles);
|
|
||||||
DEBUG(10,("close_policy_by_pipe: deleted handle list for pipe %s\n", p->name ));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Shall we allow access to this rpc? Currently this function
|
|
||||||
implements the 'restrict anonymous' setting by denying access to
|
|
||||||
anonymous users if the restrict anonymous level is > 0. Further work
|
|
||||||
will be checking a security descriptor to determine whether a user
|
|
||||||
token has enough access to access the pipe.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
BOOL pipe_access_check(pipes_struct *p)
|
|
||||||
{
|
|
||||||
/* Don't let anonymous users access this RPC if restrict
|
|
||||||
anonymous > 0 */
|
|
||||||
|
|
||||||
if (lp_restrict_anonymous() > 0) {
|
|
||||||
user_struct *user = get_valid_user_struct(p->vuid);
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
DEBUG(3, ("invalid vuid %d\n", p->vuid));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user->guest)
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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-2001,
|
|
||||||
* Copyright (C) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface to the netlogon pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_req_chal:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_req_chal(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_REQ_CHAL q_u;
|
|
||||||
NET_R_REQ_CHAL r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the challenge... */
|
|
||||||
if(!net_io_q_req_chal("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_req_chal: Failed to unmarshall NET_Q_REQ_CHAL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_req_chal(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_req_chal("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_req_chal: Failed to marshall NET_R_REQ_CHAL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_auth:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_auth(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_AUTH q_u;
|
|
||||||
NET_R_AUTH r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the challenge... */
|
|
||||||
if(!net_io_q_auth("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_auth: Failed to unmarshall NET_Q_AUTH.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_auth(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_auth("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_auth: Failed to marshall NET_R_AUTH.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_auth_2:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_auth_2(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_AUTH_2 q_u;
|
|
||||||
NET_R_AUTH_2 r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the challenge... */
|
|
||||||
if(!net_io_q_auth_2("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_auth_2: Failed to unmarshall NET_Q_AUTH_2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_auth_2(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_auth_2("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_auth_2: Failed to marshall NET_R_AUTH_2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_srv_pwset:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_srv_pwset(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_SRV_PWSET q_u;
|
|
||||||
NET_R_SRV_PWSET r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the challenge and encrypted password ... */
|
|
||||||
if(!net_io_q_srv_pwset("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_srv_pwset: Failed to unmarshall NET_Q_SRV_PWSET.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_srv_pwset(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_srv_pwset("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_srv_pwset: Failed to marshall NET_R_SRV_PWSET.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_sam_logoff:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_sam_logoff(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_SAM_LOGOFF q_u;
|
|
||||||
NET_R_SAM_LOGOFF r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!net_io_q_sam_logoff("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_sam_logoff: Failed to unmarshall NET_Q_SAM_LOGOFF.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_sam_logoff(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_sam_logoff("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_sam_logoff: Failed to marshall NET_R_SAM_LOGOFF.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_sam_logon:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_sam_logon(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_SAM_LOGON q_u;
|
|
||||||
NET_R_SAM_LOGON r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!net_io_q_sam_logon("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0, ("api_net_sam_logon: Failed to unmarshall NET_Q_SAM_LOGON.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_sam_logon(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_sam_logon("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_net_sam_logon: Failed to marshall NET_R_SAM_LOGON.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_trust_dom_list:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_trust_dom_list(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_TRUST_DOM_LIST q_u;
|
|
||||||
NET_R_TRUST_DOM_LIST r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
|
|
||||||
|
|
||||||
/* grab the lsa trusted domain list query... */
|
|
||||||
if(!net_io_q_trust_dom("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_trust_dom_list: Failed to unmarshall NET_Q_TRUST_DOM_LIST.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* construct reply. */
|
|
||||||
r_u.status = _net_trust_dom_list(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!net_io_r_trust_dom("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("net_reply_trust_dom_list: Failed to marshall NET_R_TRUST_DOM_LIST.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_logon_ctrl2:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_logon_ctrl2(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_LOGON_CTRL2 q_u;
|
|
||||||
NET_R_LOGON_CTRL2 r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
|
|
||||||
|
|
||||||
/* grab the lsa netlogon ctrl2 query... */
|
|
||||||
if(!net_io_q_logon_ctrl2("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_logon_ctrl2: Failed to unmarshall NET_Q_LOGON_CTRL2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_logon_ctrl2(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!net_io_r_logon_ctrl2("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
api_net_logon_ctrl:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_net_logon_ctrl(pipes_struct *p)
|
|
||||||
{
|
|
||||||
NET_Q_LOGON_CTRL q_u;
|
|
||||||
NET_R_LOGON_CTRL r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_logon_ctrl: %d\n", __LINE__));
|
|
||||||
|
|
||||||
/* grab the lsa netlogon ctrl query... */
|
|
||||||
if(!net_io_q_logon_ctrl("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_net_logon_ctrl: Failed to unmarshall NET_Q_LOGON_CTRL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _net_logon_ctrl(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!net_io_r_logon_ctrl("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL2.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
array of \PIPE\NETLOGON operations
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_NETLOG_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_net_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static struct api_struct api_net_cmds [] =
|
|
||||||
{
|
|
||||||
{ "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal },
|
|
||||||
{ "NET_AUTH" , NET_AUTH , api_net_auth },
|
|
||||||
{ "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 },
|
|
||||||
{ "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset },
|
|
||||||
{ "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon },
|
|
||||||
{ "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff },
|
|
||||||
{ "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
|
|
||||||
{ "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
|
|
||||||
{ "NET_LOGON_CTRL" , NET_LOGON_CTRL , api_net_logon_ctrl }
|
|
||||||
};
|
|
||||||
|
|
||||||
return rpc_pipe_register_commands("NETLOGON", "lsass", api_net_cmds,
|
|
||||||
sizeof(api_net_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
@ -1,743 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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-2001.
|
|
||||||
* Copyirht (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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the implementation of the netlogon pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
init_net_r_req_chal:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c,
|
|
||||||
DOM_CHAL *srv_chal, NTSTATUS status)
|
|
||||||
{
|
|
||||||
DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__));
|
|
||||||
memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
|
|
||||||
r_c->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
error messages cropping up when using nltest.exe...
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
#define ERROR_NO_SUCH_DOMAIN 0x54b
|
|
||||||
#define ERROR_NO_LOGON_SERVERS 0x51f
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
net_reply_logon_ctrl:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
/* Some flag values reverse engineered from NLTEST.EXE */
|
|
||||||
|
|
||||||
#define LOGON_CTRL_IN_SYNC 0x00
|
|
||||||
#define LOGON_CTRL_REPL_NEEDED 0x01
|
|
||||||
#define LOGON_CTRL_REPL_IN_PROGRESS 0x02
|
|
||||||
|
|
||||||
NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u,
|
|
||||||
NET_R_LOGON_CTRL *r_u)
|
|
||||||
{
|
|
||||||
uint32 flags = 0x0;
|
|
||||||
uint32 pdc_connection_status = 0x00; /* Maybe a win32 error code? */
|
|
||||||
|
|
||||||
/* Setup the Logon Control response */
|
|
||||||
|
|
||||||
init_net_r_logon_ctrl(r_u, q_u->query_level, flags,
|
|
||||||
pdc_connection_status);
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Send a message to smbd to do a sam synchronisation
|
|
||||||
**************************************************************************/
|
|
||||||
static void send_sync_message(void)
|
|
||||||
{
|
|
||||||
TDB_CONTEXT *tdb;
|
|
||||||
|
|
||||||
tdb = tdb_open_log(lock_path("connections.tdb"), 0,
|
|
||||||
TDB_DEFAULT, O_RDONLY, 0);
|
|
||||||
|
|
||||||
if (!tdb) {
|
|
||||||
DEBUG(3, ("send_sync_message(): failed to open connections "
|
|
||||||
"database\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(3, ("sending sam synchronisation message\n"));
|
|
||||||
|
|
||||||
message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False, NULL);
|
|
||||||
|
|
||||||
tdb_close(tdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
net_reply_logon_ctrl2:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u)
|
|
||||||
{
|
|
||||||
uint32 flags = 0x0;
|
|
||||||
uint32 pdc_connection_status = 0x0;
|
|
||||||
uint32 logon_attempts = 0x0;
|
|
||||||
uint32 tc_status = ERROR_NO_LOGON_SERVERS;
|
|
||||||
const char *trusted_domain = "test_domain";
|
|
||||||
|
|
||||||
DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
|
|
||||||
q_u->function_code, q_u->query_level, q_u->switch_value));
|
|
||||||
|
|
||||||
DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
|
|
||||||
|
|
||||||
|
|
||||||
/* set up the Logon Control2 response */
|
|
||||||
init_net_r_logon_ctrl2(r_u, q_u->query_level,
|
|
||||||
flags, pdc_connection_status, logon_attempts,
|
|
||||||
tc_status, trusted_domain);
|
|
||||||
|
|
||||||
if (lp_server_role() == ROLE_DOMAIN_BDC)
|
|
||||||
send_sync_message();
|
|
||||||
|
|
||||||
DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
net_reply_trust_dom_list:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_trust_dom_list(pipes_struct *p, NET_Q_TRUST_DOM_LIST *q_u, NET_R_TRUST_DOM_LIST *r_u)
|
|
||||||
{
|
|
||||||
const char *trusted_domain = "test_domain";
|
|
||||||
uint32 num_trust_domains = 1;
|
|
||||||
|
|
||||||
DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
|
|
||||||
|
|
||||||
/* set up the Trusted Domain List response */
|
|
||||||
init_r_trust_dom(r_u, num_trust_domains, trusted_domain);
|
|
||||||
|
|
||||||
DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************************
|
|
||||||
init_net_r_srv_pwset:
|
|
||||||
***********************************************************************************/
|
|
||||||
|
|
||||||
static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
|
|
||||||
DOM_CRED *srv_cred, NTSTATUS status)
|
|
||||||
{
|
|
||||||
DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
|
|
||||||
|
|
||||||
memcpy(&r_s->srv_cred, srv_cred, sizeof(r_s->srv_cred));
|
|
||||||
r_s->status = status;
|
|
||||||
|
|
||||||
DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
gets a machine password entry. checks access rights of the host.
|
|
||||||
******************************************************************/
|
|
||||||
|
|
||||||
static BOOL get_md4pw(char *md4pw, char *mach_acct)
|
|
||||||
{
|
|
||||||
SAM_ACCOUNT *sampass = NULL;
|
|
||||||
const uint8 *pass;
|
|
||||||
BOOL ret;
|
|
||||||
uint32 acct_ctrl;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Currently this code is redundent as we already have a filter
|
|
||||||
* by hostname list. What this code really needs to do is to
|
|
||||||
* get a hosts allowed/hosts denied list from the SAM database
|
|
||||||
* on a per user basis, and make the access decision there.
|
|
||||||
* I will leave this code here for now as a reminder to implement
|
|
||||||
* this at a later date. JRA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
|
|
||||||
client_name(), client_addr()))
|
|
||||||
{
|
|
||||||
DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* JRA. This is ok as it is only used for generating the challenge. */
|
|
||||||
become_root();
|
|
||||||
ret=pdb_getsampwnam(sampass, mach_acct);
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
if (ret==False) {
|
|
||||||
DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
acct_ctrl = pdb_get_acct_ctrl(sampass);
|
|
||||||
if (!(acct_ctrl & ACB_DISABLED) &&
|
|
||||||
((acct_ctrl & ACB_DOMTRUST) ||
|
|
||||||
(acct_ctrl & ACB_WSTRUST) ||
|
|
||||||
(acct_ctrl & ACB_SVRTRUST)) &&
|
|
||||||
((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
|
|
||||||
memcpy(md4pw, pass, 16);
|
|
||||||
dump_data(5, md4pw, 16);
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return False;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_req_chal
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
|
|
||||||
rpcstr_pull(p->dc.remote_machine,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
|
|
||||||
|
|
||||||
/* create a server challenge for the client */
|
|
||||||
/* Set these to random values. */
|
|
||||||
generate_random_buffer(p->dc.srv_chal.data, 8, False);
|
|
||||||
|
|
||||||
memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
|
|
||||||
|
|
||||||
memcpy(p->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
|
|
||||||
memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
|
|
||||||
|
|
||||||
p->dc.challenge_sent = True;
|
|
||||||
/* set up the LSA REQUEST CHALLENGE response */
|
|
||||||
init_net_r_req_chal(r_u, &p->dc.srv_chal, status);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
init_net_r_auth:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS status)
|
|
||||||
{
|
|
||||||
memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
|
|
||||||
r_a->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_auth
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
DOM_CHAL srv_cred;
|
|
||||||
UTIME srv_time;
|
|
||||||
fstring mach_acct;
|
|
||||||
|
|
||||||
srv_time.time = 0;
|
|
||||||
|
|
||||||
rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
|
|
||||||
|
|
||||||
if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
|
|
||||||
|
|
||||||
/* from client / server challenges and md4 password, generate sess key */
|
|
||||||
cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
|
|
||||||
p->dc.md4pw, p->dc.sess_key);
|
|
||||||
|
|
||||||
/* check that the client credentials are valid */
|
|
||||||
if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
|
|
||||||
|
|
||||||
/* create server challenge for inclusion in the reply */
|
|
||||||
cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
|
|
||||||
|
|
||||||
/* copy the received client credentials for use next time */
|
|
||||||
memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
|
|
||||||
/* Save the machine account name. */
|
|
||||||
fstrcpy(p->dc.mach_acct, mach_acct);
|
|
||||||
|
|
||||||
p->dc.authenticated = True;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up the LSA AUTH response */
|
|
||||||
init_net_r_auth(r_u, &srv_cred, status);
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
init_net_r_auth_2:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
|
|
||||||
DOM_CHAL *resp_cred, NEG_FLAGS *flgs, NTSTATUS status)
|
|
||||||
{
|
|
||||||
memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
|
|
||||||
memcpy(&r_a->srv_flgs, flgs, sizeof(r_a->srv_flgs));
|
|
||||||
r_a->status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_auth_2
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
DOM_CHAL srv_cred;
|
|
||||||
UTIME srv_time;
|
|
||||||
NEG_FLAGS srv_flgs;
|
|
||||||
fstring mach_acct;
|
|
||||||
|
|
||||||
srv_time.time = 0;
|
|
||||||
|
|
||||||
rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
|
|
||||||
|
|
||||||
if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
|
|
||||||
|
|
||||||
/* from client / server challenges and md4 password, generate sess key */
|
|
||||||
cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
|
|
||||||
p->dc.md4pw, p->dc.sess_key);
|
|
||||||
|
|
||||||
/* check that the client credentials are valid */
|
|
||||||
if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
|
|
||||||
|
|
||||||
/* create server challenge for inclusion in the reply */
|
|
||||||
cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
|
|
||||||
|
|
||||||
/* copy the received client credentials for use next time */
|
|
||||||
memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
|
|
||||||
|
|
||||||
/* Save the machine account name. */
|
|
||||||
fstrcpy(p->dc.mach_acct, mach_acct);
|
|
||||||
|
|
||||||
p->dc.authenticated = True;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status = NT_STATUS_ACCESS_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
srv_flgs.neg_flags = 0x000001ff;
|
|
||||||
|
|
||||||
/* set up the LSA AUTH 2 response */
|
|
||||||
init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status);
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_srv_pwset
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_ACCESS_DENIED;
|
|
||||||
DOM_CRED srv_cred;
|
|
||||||
pstring workstation;
|
|
||||||
SAM_ACCOUNT *sampass=NULL;
|
|
||||||
BOOL ret = False;
|
|
||||||
unsigned char pwd[16];
|
|
||||||
int i;
|
|
||||||
uint32 acct_ctrl;
|
|
||||||
|
|
||||||
/* checks and updates credentials. creates reply credentials */
|
|
||||||
if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
|
|
||||||
|
|
||||||
DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
|
|
||||||
|
|
||||||
rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
|
|
||||||
sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
|
|
||||||
|
|
||||||
DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct));
|
|
||||||
|
|
||||||
pdb_init_sam(&sampass);
|
|
||||||
|
|
||||||
become_root();
|
|
||||||
ret=pdb_getsampwnam(sampass, p->dc.mach_acct);
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
/* Ensure the account exists and is a machine account. */
|
|
||||||
|
|
||||||
acct_ctrl = pdb_get_acct_ctrl(sampass);
|
|
||||||
|
|
||||||
if (!(ret
|
|
||||||
&& (acct_ctrl & ACB_WSTRUST ||
|
|
||||||
acct_ctrl & ACB_SVRTRUST ||
|
|
||||||
acct_ctrl & ACB_DOMTRUST))) {
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_ACCOUNT_DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(100,("Server password set : new given value was :\n"));
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
DEBUG(100,("%02X ", q_u->pwd[i]));
|
|
||||||
DEBUG(100,("\n"));
|
|
||||||
|
|
||||||
cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
|
|
||||||
|
|
||||||
/* lies! nt and lm passwords are _not_ the same: don't care */
|
|
||||||
if (!pdb_set_lanman_passwd (sampass, pwd, PDB_CHANGED)) {
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) {
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pdb_set_pass_changed_now (sampass)) {
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
/* Not quite sure what this one qualifies as, but this will do */
|
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
become_root();
|
|
||||||
ret = pdb_update_sam_account (sampass);
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
status = NT_STATUS_OK;
|
|
||||||
|
|
||||||
/* set up the LSA Server Password Set response */
|
|
||||||
init_net_r_srv_pwset(r_u, &srv_cred, status);
|
|
||||||
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_sam_logoff:
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
|
|
||||||
{
|
|
||||||
DOM_CRED srv_cred;
|
|
||||||
|
|
||||||
if (!get_valid_user_struct(p->vuid))
|
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
|
||||||
|
|
||||||
/* checks and updates credentials. creates reply credentials */
|
|
||||||
if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred,
|
|
||||||
&q_u->sam_id.client.cred, &srv_cred)))
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
|
|
||||||
|
|
||||||
/* XXXX maybe we want to say 'no', reject the client's credentials */
|
|
||||||
r_u->buffer_creds = 1; /* yes, we have valid server credentials */
|
|
||||||
memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
|
|
||||||
|
|
||||||
r_u->status = NT_STATUS_OK;
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
_net_sam_logon
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
NET_USER_INFO_3 *usr_info = NULL;
|
|
||||||
NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
|
|
||||||
DOM_CRED srv_cred;
|
|
||||||
UNISTR2 *uni_samlogon_user = NULL;
|
|
||||||
UNISTR2 *uni_samlogon_domain = NULL;
|
|
||||||
UNISTR2 *uni_samlogon_workstation = NULL;
|
|
||||||
fstring nt_username, nt_domain, nt_workstation;
|
|
||||||
auth_usersupplied_info *user_info = NULL;
|
|
||||||
auth_serversupplied_info *server_info = NULL;
|
|
||||||
extern userdom_struct current_user_info;
|
|
||||||
SAM_ACCOUNT *sampw;
|
|
||||||
|
|
||||||
usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
|
|
||||||
if (!usr_info)
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
|
|
||||||
ZERO_STRUCTP(usr_info);
|
|
||||||
|
|
||||||
/* store the user information, if there is any. */
|
|
||||||
r_u->user = usr_info;
|
|
||||||
r_u->switch_value = 0; /* indicates no info */
|
|
||||||
r_u->auth_resp = 1; /* authoritative response */
|
|
||||||
r_u->switch_value = 3; /* indicates type of validation user info */
|
|
||||||
|
|
||||||
if (!get_valid_user_struct(p->vuid))
|
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
|
||||||
|
|
||||||
/* checks and updates credentials. creates reply credentials */
|
|
||||||
if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)))
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
|
|
||||||
|
|
||||||
r_u->buffer_creds = 1; /* yes, we have valid server credentials */
|
|
||||||
memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
|
|
||||||
|
|
||||||
/* find the username */
|
|
||||||
|
|
||||||
switch (q_u->sam_id.logon_level) {
|
|
||||||
case INTERACTIVE_LOGON_TYPE:
|
|
||||||
uni_samlogon_user = &ctr->auth.id1.uni_user_name;
|
|
||||||
uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
|
|
||||||
|
|
||||||
uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
|
|
||||||
|
|
||||||
DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
|
|
||||||
break;
|
|
||||||
case NET_LOGON_TYPE:
|
|
||||||
uni_samlogon_user = &ctr->auth.id2.uni_user_name;
|
|
||||||
uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
|
|
||||||
uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
|
|
||||||
|
|
||||||
DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DEBUG(2,("SAM Logon: unsupported switch value\n"));
|
|
||||||
return NT_STATUS_INVALID_INFO_CLASS;
|
|
||||||
} /* end switch */
|
|
||||||
|
|
||||||
/* check username exists */
|
|
||||||
|
|
||||||
rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
|
|
||||||
rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
|
|
||||||
rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
|
|
||||||
|
|
||||||
DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username,
|
|
||||||
nt_workstation, nt_domain));
|
|
||||||
|
|
||||||
fstrcpy(current_user_info.smb_name, nt_username);
|
|
||||||
sub_set_smb_name(nt_username);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert to a UNIX username.
|
|
||||||
*/
|
|
||||||
|
|
||||||
DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
|
|
||||||
|
|
||||||
switch (ctr->switch_value) {
|
|
||||||
case NET_LOGON_TYPE:
|
|
||||||
{
|
|
||||||
struct auth_context *auth_context = NULL;
|
|
||||||
if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Standard challenge/response authenticaion */
|
|
||||||
if (!make_user_info_netlogon_network(&user_info,
|
|
||||||
nt_username, nt_domain,
|
|
||||||
nt_workstation,
|
|
||||||
ctr->auth.id2.lm_chal_resp.buffer,
|
|
||||||
ctr->auth.id2.lm_chal_resp.str_str_len,
|
|
||||||
ctr->auth.id2.nt_chal_resp.buffer,
|
|
||||||
ctr->auth.id2.nt_chal_resp.str_str_len)) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
} else {
|
|
||||||
status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
|
|
||||||
}
|
|
||||||
(auth_context->free)(&auth_context);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INTERACTIVE_LOGON_TYPE:
|
|
||||||
/* 'Interactive' autheticaion, supplies the password in its
|
|
||||||
MD4 form, encrypted with the session key. We will
|
|
||||||
convert this to chellange/responce for the auth
|
|
||||||
subsystem to chew on */
|
|
||||||
{
|
|
||||||
struct auth_context *auth_context = NULL;
|
|
||||||
const uint8 *chal;
|
|
||||||
if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
chal = auth_context->get_ntlm_challenge(auth_context);
|
|
||||||
|
|
||||||
if (!make_user_info_netlogon_interactive(&user_info,
|
|
||||||
nt_username, nt_domain,
|
|
||||||
nt_workstation, chal,
|
|
||||||
ctr->auth.id1.lm_owf.data,
|
|
||||||
ctr->auth.id1.nt_owf.data,
|
|
||||||
p->dc.sess_key)) {
|
|
||||||
status = NT_STATUS_NO_MEMORY;
|
|
||||||
} else {
|
|
||||||
status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
(auth_context->free)(&auth_context);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
DEBUG(2,("SAM Logon: unsupported switch value\n"));
|
|
||||||
return NT_STATUS_INVALID_INFO_CLASS;
|
|
||||||
} /* end switch */
|
|
||||||
|
|
||||||
free_user_info(&user_info);
|
|
||||||
|
|
||||||
DEBUG(5, ("_net_sam_logon: check_password returned status %s\n",
|
|
||||||
nt_errstr(status)));
|
|
||||||
|
|
||||||
/* Check account and password */
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(status)) {
|
|
||||||
free_server_info(&server_info);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server_info->guest) {
|
|
||||||
/* We don't like guest domain logons... */
|
|
||||||
DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
|
|
||||||
free_server_info(&server_info);
|
|
||||||
return NT_STATUS_LOGON_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is the point at which, if the login was successful, that
|
|
||||||
the SAM Local Security Authority should record that the user is
|
|
||||||
logged in to the domain. */
|
|
||||||
|
|
||||||
{
|
|
||||||
DOM_GID *gids = NULL;
|
|
||||||
const DOM_SID *user_sid = NULL;
|
|
||||||
const DOM_SID *group_sid = NULL;
|
|
||||||
DOM_SID domain_sid;
|
|
||||||
uint32 user_rid, group_rid;
|
|
||||||
|
|
||||||
int num_gids = 0;
|
|
||||||
pstring my_name;
|
|
||||||
fstring user_sid_string;
|
|
||||||
fstring group_sid_string;
|
|
||||||
uchar user_sess_key[16];
|
|
||||||
uchar netlogon_sess_key[16];
|
|
||||||
|
|
||||||
sampw = server_info->sam_account;
|
|
||||||
|
|
||||||
/* set up pointer indicating user/password failed to be found */
|
|
||||||
usr_info->ptr_user_info = 0;
|
|
||||||
|
|
||||||
user_sid = pdb_get_user_sid(sampw);
|
|
||||||
group_sid = pdb_get_group_sid(sampw);
|
|
||||||
|
|
||||||
sid_copy(&domain_sid, user_sid);
|
|
||||||
sid_split_rid(&domain_sid, &user_rid);
|
|
||||||
|
|
||||||
if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
|
|
||||||
DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",
|
|
||||||
pdb_get_domain(sampw), pdb_get_username(sampw),
|
|
||||||
sid_to_string(user_sid_string, user_sid),
|
|
||||||
sid_to_string(group_sid_string, group_sid)));
|
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pstrcpy(my_name, lp_netbios_name());
|
|
||||||
|
|
||||||
if (!NT_STATUS_IS_OK(status
|
|
||||||
= nt_token_to_group_list(p->mem_ctx,
|
|
||||||
&domain_sid,
|
|
||||||
server_info->ptok,
|
|
||||||
&num_gids,
|
|
||||||
&gids))) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZERO_STRUCT(netlogon_sess_key);
|
|
||||||
memcpy(netlogon_sess_key, p->dc.sess_key, 8);
|
|
||||||
memcpy(user_sess_key, server_info->session_key, sizeof(user_sess_key));
|
|
||||||
SamOEMhash(user_sess_key, netlogon_sess_key, 16);
|
|
||||||
ZERO_STRUCT(netlogon_sess_key);
|
|
||||||
|
|
||||||
init_net_user_info3(p->mem_ctx, usr_info,
|
|
||||||
user_rid,
|
|
||||||
group_rid,
|
|
||||||
|
|
||||||
pdb_get_username(sampw),
|
|
||||||
pdb_get_fullname(sampw),
|
|
||||||
pdb_get_homedir(sampw),
|
|
||||||
pdb_get_dir_drive(sampw),
|
|
||||||
pdb_get_logon_script(sampw),
|
|
||||||
pdb_get_profile_path(sampw),
|
|
||||||
pdb_get_logon_time(sampw),
|
|
||||||
get_time_t_max(),
|
|
||||||
get_time_t_max(),
|
|
||||||
pdb_get_pass_last_set_time(sampw),
|
|
||||||
pdb_get_pass_can_change_time(sampw),
|
|
||||||
pdb_get_pass_must_change_time(sampw),
|
|
||||||
|
|
||||||
0, /* logon_count */
|
|
||||||
0, /* bad_pw_count */
|
|
||||||
num_gids, /* uint32 num_groups */
|
|
||||||
gids , /* DOM_GID *gids */
|
|
||||||
0x20 , /* uint32 user_flgs (?) */
|
|
||||||
user_sess_key,
|
|
||||||
my_name , /* char *logon_srv */
|
|
||||||
pdb_get_domain(sampw),
|
|
||||||
&domain_sid, /* DOM_SID *dom_sid */
|
|
||||||
/* Should be users domain sid, not servers - for trusted domains */
|
|
||||||
|
|
||||||
NULL); /* char *other_sids */
|
|
||||||
ZERO_STRUCT(user_sess_key);
|
|
||||||
}
|
|
||||||
free_server_info(&server_info);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,400 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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) Marc Jacobsen 2000,
|
|
||||||
* Copyright (C) Jeremy Allison 2001,
|
|
||||||
* Copyright (C) Gerald Carter 2002,
|
|
||||||
* Copyright (C) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface for the registry functions. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_close
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_close(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_CLOSE q_u;
|
|
||||||
REG_R_CLOSE r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg unknown 1 */
|
|
||||||
if(!reg_io_q_close("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_close(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_close("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_open_khlm
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_open_hklm(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_OPEN_HKLM q_u;
|
|
||||||
REG_R_OPEN_HKLM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg open */
|
|
||||||
if(!reg_io_q_open_hklm("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_open_hklm(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_open_hklm("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_open_khu
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_open_hku(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_OPEN_HKU q_u;
|
|
||||||
REG_R_OPEN_HKU r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg open */
|
|
||||||
if(!reg_io_q_open_hku("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_open_hku(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_open_hku("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_open_khcr
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_open_hkcr(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_OPEN_HKCR q_u;
|
|
||||||
REG_R_OPEN_HKCR r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg open */
|
|
||||||
if(!reg_io_q_open_hkcr("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_open_hkcr(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_open_hkcr("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_open_entry
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_open_entry(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_OPEN_ENTRY q_u;
|
|
||||||
REG_R_OPEN_ENTRY r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg open entry */
|
|
||||||
if(!reg_io_q_open_entry("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* construct reply. */
|
|
||||||
r_u.status = _reg_open_entry(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_open_entry("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_info
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_INFO q_u;
|
|
||||||
REG_R_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg unknown 0x11*/
|
|
||||||
if(!reg_io_q_info("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_info("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_shutdown
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_shutdown(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_SHUTDOWN q_u;
|
|
||||||
REG_R_SHUTDOWN r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg shutdown */
|
|
||||||
if(!reg_io_q_shutdown("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_shutdown(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_shutdown("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_abort_shutdown
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_abort_shutdown(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_ABORT_SHUTDOWN q_u;
|
|
||||||
REG_R_ABORT_SHUTDOWN r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the reg shutdown */
|
|
||||||
if(!reg_io_q_abort_shutdown("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_abort_shutdown(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_abort_shutdown("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_query_key
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_query_key(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_QUERY_KEY q_u;
|
|
||||||
REG_R_QUERY_KEY r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!reg_io_q_query_key("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_query_key(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_query_key("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_unknown_1a
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_unknown_1a(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_UNKNOWN_1A q_u;
|
|
||||||
REG_R_UNKNOWN_1A r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!reg_io_q_unknown_1a("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_unknown_1a(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_unknown_1a("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_enum_key
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_enum_key(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_ENUM_KEY q_u;
|
|
||||||
REG_R_ENUM_KEY r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!reg_io_q_enum_key("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_enum_key(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_enum_key("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_enum_value
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_enum_value(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_ENUM_VALUE q_u;
|
|
||||||
REG_R_ENUM_VALUE r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!reg_io_q_enum_val("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_enum_value(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_enum_val("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_reg_save_key
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_reg_save_key(pipes_struct *p)
|
|
||||||
{
|
|
||||||
REG_Q_SAVE_KEY q_u;
|
|
||||||
REG_R_SAVE_KEY r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
if(!reg_io_q_save_key("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _reg_save_key(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!reg_io_r_save_key("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
array of \PIPE\reg operations
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_REG_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_reg_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static struct api_struct api_reg_cmds[] =
|
|
||||||
{
|
|
||||||
{ "REG_CLOSE" , REG_CLOSE , api_reg_close },
|
|
||||||
{ "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry },
|
|
||||||
{ "REG_OPEN_HKCR" , REG_OPEN_HKCR , api_reg_open_hkcr },
|
|
||||||
{ "REG_OPEN_HKLM" , REG_OPEN_HKLM , api_reg_open_hklm },
|
|
||||||
{ "REG_OPEN_HKU" , REG_OPEN_HKU , api_reg_open_hku },
|
|
||||||
{ "REG_ENUM_KEY" , REG_ENUM_KEY , api_reg_enum_key },
|
|
||||||
{ "REG_ENUM_VALUE" , REG_ENUM_VALUE , api_reg_enum_value },
|
|
||||||
{ "REG_QUERY_KEY" , REG_QUERY_KEY , api_reg_query_key },
|
|
||||||
{ "REG_INFO" , REG_INFO , api_reg_info },
|
|
||||||
{ "REG_SHUTDOWN" , REG_SHUTDOWN , api_reg_shutdown },
|
|
||||||
{ "REG_ABORT_SHUTDOWN" , REG_ABORT_SHUTDOWN , api_reg_abort_shutdown },
|
|
||||||
{ "REG_UNKNOWN_1A" , REG_UNKNOWN_1A , api_reg_unknown_1a },
|
|
||||||
{ "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key }
|
|
||||||
};
|
|
||||||
return rpc_pipe_register_commands("winreg", "winreg", api_reg_cmds,
|
|
||||||
sizeof(api_reg_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
@ -1,664 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 2001.
|
|
||||||
* Copyright (C) Gerald Carter 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Implementation of registry functions. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
#define REGSTR_PRODUCTTYPE "ProductType"
|
|
||||||
#define REG_PT_WINNT "WinNT"
|
|
||||||
#define REG_PT_LANMANNT "LanmanNT"
|
|
||||||
#define REG_PT_SERVERNT "ServerNT"
|
|
||||||
|
|
||||||
#define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
|
|
||||||
((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
|
|
||||||
|
|
||||||
|
|
||||||
static REGISTRY_KEY *regkeys_list;
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
free() function for REGISTRY_KEY
|
|
||||||
*****************************************************************/
|
|
||||||
|
|
||||||
static void free_regkey_info(void *ptr)
|
|
||||||
{
|
|
||||||
REGISTRY_KEY *info = (REGISTRY_KEY*)ptr;
|
|
||||||
|
|
||||||
DLIST_REMOVE(regkeys_list, info);
|
|
||||||
|
|
||||||
SAFE_FREE(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
Find a registry key handle and return a REGISTRY_KEY
|
|
||||||
*****************************************************************/
|
|
||||||
|
|
||||||
static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
|
|
||||||
{
|
|
||||||
REGISTRY_KEY *regkey = NULL;
|
|
||||||
|
|
||||||
if(!find_policy_by_hnd(p,hnd,(void **)®key)) {
|
|
||||||
DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return regkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Function for open a new registry handle and creating a handle
|
|
||||||
Note that P should be valid & hnd should already have space
|
|
||||||
|
|
||||||
When we open a key, we store the full path to the key as
|
|
||||||
HK[LM|U]\<key>\<key>\...
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static NTSTATUS open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent,
|
|
||||||
const char *subkeyname, uint32 access_granted )
|
|
||||||
{
|
|
||||||
REGISTRY_KEY *regkey = NULL;
|
|
||||||
NTSTATUS result = NT_STATUS_OK;
|
|
||||||
REGSUBKEY_CTR subkeys;
|
|
||||||
pstring subkeyname2;
|
|
||||||
int subkey_len;
|
|
||||||
|
|
||||||
DEBUG(7,("open_registry_key: name = [%s][%s]\n",
|
|
||||||
parent ? parent->name : "NULL", subkeyname));
|
|
||||||
|
|
||||||
/* strip any trailing '\'s */
|
|
||||||
pstrcpy( subkeyname2, subkeyname );
|
|
||||||
subkey_len = strlen ( subkeyname2 );
|
|
||||||
if ( subkey_len && subkeyname2[subkey_len-1] == '\\' )
|
|
||||||
subkeyname2[subkey_len-1] = '\0';
|
|
||||||
|
|
||||||
if ((regkey=(REGISTRY_KEY*)malloc(sizeof(REGISTRY_KEY))) == NULL)
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
|
|
||||||
ZERO_STRUCTP( regkey );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* very crazy, but regedit.exe on Win2k will attempt to call
|
|
||||||
* REG_OPEN_ENTRY with a keyname of "". We should return a new
|
|
||||||
* (second) handle here on the key->name. regedt32.exe does
|
|
||||||
* not do this stupidity. --jerry
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( !subkey_len ) {
|
|
||||||
pstrcpy( regkey->name, parent->name );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pstrcpy( regkey->name, "" );
|
|
||||||
if ( parent ) {
|
|
||||||
pstrcat( regkey->name, parent->name );
|
|
||||||
pstrcat( regkey->name, "\\" );
|
|
||||||
}
|
|
||||||
pstrcat( regkey->name, subkeyname2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look up the table of registry I/O operations */
|
|
||||||
|
|
||||||
if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) {
|
|
||||||
DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
|
|
||||||
regkey->name ));
|
|
||||||
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if the path really exists; failed is indicated by -1 */
|
|
||||||
/* if the subkey count failed, bail out */
|
|
||||||
|
|
||||||
ZERO_STRUCTP( &subkeys );
|
|
||||||
|
|
||||||
regsubkey_ctr_init( &subkeys );
|
|
||||||
|
|
||||||
if ( fetch_reg_keys( regkey, &subkeys ) == -1 ) {
|
|
||||||
|
|
||||||
/* don't really know what to return here */
|
|
||||||
result = NT_STATUS_NO_SUCH_FILE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/*
|
|
||||||
* This would previously return NT_STATUS_TOO_MANY_SECRETS
|
|
||||||
* that doesn't sound quite right to me --jerry
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) )
|
|
||||||
result = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clean up */
|
|
||||||
|
|
||||||
regsubkey_ctr_destroy( &subkeys );
|
|
||||||
|
|
||||||
if ( ! NT_STATUS_IS_OK(result) )
|
|
||||||
SAFE_FREE( regkey );
|
|
||||||
else
|
|
||||||
DLIST_ADD( regkeys_list, regkey );
|
|
||||||
|
|
||||||
|
|
||||||
DEBUG(7,("open_registry_key: exit\n"));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Function for open a new registry handle and creating a handle
|
|
||||||
Note that P should be valid & hnd should already have space
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
|
|
||||||
{
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
|
|
||||||
|
|
||||||
if ( !regkey ) {
|
|
||||||
DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
close_policy_hnd(p, hnd);
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
retrieve information about the subkeys
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
|
|
||||||
{
|
|
||||||
int num_subkeys, i;
|
|
||||||
uint32 max_len;
|
|
||||||
REGSUBKEY_CTR subkeys;
|
|
||||||
uint32 len;
|
|
||||||
|
|
||||||
if ( !key )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
ZERO_STRUCTP( &subkeys );
|
|
||||||
|
|
||||||
regsubkey_ctr_init( &subkeys );
|
|
||||||
|
|
||||||
if ( fetch_reg_keys( key, &subkeys ) == -1 )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* find the longest string */
|
|
||||||
|
|
||||||
max_len = 0;
|
|
||||||
num_subkeys = regsubkey_ctr_numkeys( &subkeys );
|
|
||||||
|
|
||||||
for ( i=0; i<num_subkeys; i++ ) {
|
|
||||||
len = strlen( regsubkey_ctr_specific_key(&subkeys, i) );
|
|
||||||
max_len = MAX(max_len, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
*maxnum = num_subkeys;
|
|
||||||
*maxlen = max_len*2;
|
|
||||||
|
|
||||||
regsubkey_ctr_destroy( &subkeys );
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
retrieve information about the values. We don't store values
|
|
||||||
here. The registry tdb is intended to be a frontend to oether
|
|
||||||
Samba tdb's (such as ntdrivers.tdb).
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum,
|
|
||||||
uint32 *maxlen, uint32 *maxsize )
|
|
||||||
{
|
|
||||||
REGVAL_CTR values;
|
|
||||||
REGISTRY_VALUE *val;
|
|
||||||
uint32 sizemax, lenmax;
|
|
||||||
int i, num_values;
|
|
||||||
|
|
||||||
if ( !key )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
|
|
||||||
ZERO_STRUCTP( &values );
|
|
||||||
|
|
||||||
regval_ctr_init( &values );
|
|
||||||
|
|
||||||
if ( fetch_reg_values( key, &values ) == -1 )
|
|
||||||
return False;
|
|
||||||
|
|
||||||
lenmax = sizemax = 0;
|
|
||||||
num_values = regval_ctr_numvals( &values );
|
|
||||||
|
|
||||||
val = regval_ctr_specific_value( &values, 0 );
|
|
||||||
|
|
||||||
for ( i=0; i<num_values && val; i++ )
|
|
||||||
{
|
|
||||||
lenmax = MAX(lenmax, strlen(val->valuename)+1 );
|
|
||||||
sizemax = MAX(sizemax, val->size );
|
|
||||||
|
|
||||||
val = regval_ctr_specific_value( &values, i );
|
|
||||||
}
|
|
||||||
|
|
||||||
*maxnum = num_values;
|
|
||||||
*maxlen = lenmax;
|
|
||||||
*maxsize = sizemax;
|
|
||||||
|
|
||||||
regval_ctr_destroy( &values );
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
reg_close
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
|
|
||||||
{
|
|
||||||
/* set up the REG unknown_1 response */
|
|
||||||
ZERO_STRUCT(r_u->pol);
|
|
||||||
|
|
||||||
/* close the policy handle */
|
|
||||||
if (!close_registry_key(p, &q_u->pol))
|
|
||||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
|
|
||||||
{
|
|
||||||
return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u)
|
|
||||||
{
|
|
||||||
return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
|
|
||||||
{
|
|
||||||
return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
reg_reply_open_entry
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY *r_u)
|
|
||||||
{
|
|
||||||
POLICY_HND pol;
|
|
||||||
fstring name;
|
|
||||||
REGISTRY_KEY *key = find_regkey_index_by_hnd(p, &q_u->pol);
|
|
||||||
NTSTATUS result;
|
|
||||||
|
|
||||||
DEBUG(5,("reg_open_entry: Enter\n"));
|
|
||||||
|
|
||||||
if ( !key )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0);
|
|
||||||
|
|
||||||
result = open_registry_key( p, &pol, key, name, 0x0 );
|
|
||||||
|
|
||||||
init_reg_r_open_entry( r_u, &pol, result );
|
|
||||||
|
|
||||||
DEBUG(5,("reg_open_entry: Exit\n"));
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
reg_reply_info
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_NO_SUCH_FILE;
|
|
||||||
fstring name;
|
|
||||||
const char *value_ascii = "";
|
|
||||||
fstring value;
|
|
||||||
int value_length;
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
REGISTRY_VALUE *val = NULL;
|
|
||||||
REGVAL_CTR regvals;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_info: Enter\n"));
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
|
|
||||||
|
|
||||||
rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0);
|
|
||||||
|
|
||||||
DEBUG(5,("reg_info: looking up value: [%s]\n", name));
|
|
||||||
|
|
||||||
ZERO_STRUCTP( ®vals );
|
|
||||||
|
|
||||||
regval_ctr_init( ®vals );
|
|
||||||
|
|
||||||
/* couple of hard coded registry values */
|
|
||||||
|
|
||||||
if ( strequal(name, "RefusePasswordChange") ) {
|
|
||||||
if ( (val = (REGISTRY_VALUE*)malloc(sizeof(REGISTRY_VALUE))) == NULL ) {
|
|
||||||
DEBUG(0,("_reg_info: malloc() failed!\n"));
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
ZERO_STRUCTP( val );
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( strequal(name, REGSTR_PRODUCTTYPE) ) {
|
|
||||||
/* This makes the server look like a member server to clients */
|
|
||||||
/* which tells clients that we have our own local user and */
|
|
||||||
/* group databases and helps with ACL support. */
|
|
||||||
|
|
||||||
switch (lp_server_role()) {
|
|
||||||
case ROLE_DOMAIN_PDC:
|
|
||||||
case ROLE_DOMAIN_BDC:
|
|
||||||
value_ascii = REG_PT_LANMANNT;
|
|
||||||
break;
|
|
||||||
case ROLE_STANDALONE:
|
|
||||||
value_ascii = REG_PT_SERVERNT;
|
|
||||||
break;
|
|
||||||
case ROLE_DOMAIN_MEMBER:
|
|
||||||
value_ascii = REG_PT_WINNT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value_length = push_ucs2(value, value, value_ascii,
|
|
||||||
sizeof(value),
|
|
||||||
STR_TERMINATE|STR_NOALIGN);
|
|
||||||
regval_ctr_addvalue(®vals, REGSTR_PRODUCTTYPE, REG_SZ,
|
|
||||||
value, value_length);
|
|
||||||
|
|
||||||
val = dup_registry_value( regval_ctr_specific_value( ®vals, 0 ) );
|
|
||||||
|
|
||||||
status = NT_STATUS_OK;
|
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* else fall back to actually looking up the value */
|
|
||||||
|
|
||||||
for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ )
|
|
||||||
{
|
|
||||||
DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
|
|
||||||
if ( StrCaseCmp( val->valuename, name ) == 0 ) {
|
|
||||||
DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
|
|
||||||
status = NT_STATUS_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_registry_value( val );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
out:
|
|
||||||
new_init_reg_r_info(q_u->ptr_buf, r_u, val, status);
|
|
||||||
|
|
||||||
regval_ctr_destroy( ®vals );
|
|
||||||
free_registry_value( val );
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_info: Exit\n"));
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Implementation of REG_QUERY_KEY
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_query_key: Enter\n"));
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
if ( !get_subkey_information( regkey, &r_u->num_subkeys, &r_u->max_subkeylen ) )
|
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
|
||||||
|
|
||||||
if ( !get_value_information( regkey, &r_u->num_values, &r_u->max_valnamelen, &r_u->max_valbufsize ) )
|
|
||||||
return NT_STATUS_ACCESS_DENIED;
|
|
||||||
|
|
||||||
|
|
||||||
r_u->sec_desc = 0x00000078; /* size for key's sec_desc */
|
|
||||||
|
|
||||||
/* Win9x set this to 0x0 since it does not keep timestamps.
|
|
||||||
Doing the same here for simplicity --jerry */
|
|
||||||
|
|
||||||
ZERO_STRUCT(r_u->mod_time);
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_query_key: Exit\n"));
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Implementation of REG_UNKNOWN_1A
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1A *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_unknown_1a: Enter\n"));
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
r_u->unknown = 0x00000005; /* seems to be consistent...no idea what it means */
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_unknown_1a: Exit\n"));
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Implementation of REG_ENUM_KEY
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_enum_key(pipes_struct *p, REG_Q_ENUM_KEY *q_u, REG_R_ENUM_KEY *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
char *subkey = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_enum_key: Enter\n"));
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
|
|
||||||
|
|
||||||
if ( !fetch_reg_keys_specific( regkey, &subkey, q_u->key_index ) )
|
|
||||||
{
|
|
||||||
status = NT_STATUS_NO_MORE_ENTRIES;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
|
|
||||||
|
|
||||||
/* subkey has the string name now */
|
|
||||||
|
|
||||||
init_reg_r_enum_key( r_u, subkey, q_u->unknown_1, q_u->unknown_2 );
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_enum_key: Exit\n"));
|
|
||||||
|
|
||||||
done:
|
|
||||||
SAFE_FREE( subkey );
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Implementation of REG_ENUM_VALUE
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
REGISTRY_VALUE *val;
|
|
||||||
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_enum_value: Enter\n"));
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name));
|
|
||||||
|
|
||||||
if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) )
|
|
||||||
{
|
|
||||||
status = NT_STATUS_NO_MORE_ENTRIES;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("_reg_enum_value: retrieved value named [%s]\n", val->valuename));
|
|
||||||
|
|
||||||
/* subkey has the string name now */
|
|
||||||
|
|
||||||
init_reg_r_enum_val( r_u, val );
|
|
||||||
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_enum_value: Exit\n"));
|
|
||||||
|
|
||||||
done:
|
|
||||||
free_registry_value( val );
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
reg_shutdwon
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#define SHUTDOWN_R_STRING "-r"
|
|
||||||
#define SHUTDOWN_F_STRING "-f"
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
pstring shutdown_script;
|
|
||||||
UNISTR2 unimsg = q_u->uni_msg;
|
|
||||||
pstring message;
|
|
||||||
pstring chkmsg;
|
|
||||||
fstring timeout;
|
|
||||||
fstring r;
|
|
||||||
fstring f;
|
|
||||||
|
|
||||||
/* message */
|
|
||||||
rpcstr_pull (message, unimsg.buffer, sizeof(message), unimsg.uni_str_len*2,0);
|
|
||||||
/* security check */
|
|
||||||
alpha_strcpy (chkmsg, message, NULL, sizeof(message));
|
|
||||||
/* timeout */
|
|
||||||
snprintf(timeout, sizeof(timeout), "%d", q_u->timeout);
|
|
||||||
/* reboot */
|
|
||||||
snprintf(r, sizeof(r), (q_u->reboot) ? SHUTDOWN_R_STRING : "");
|
|
||||||
/* force */
|
|
||||||
snprintf(f, sizeof(f), (q_u->force) ? SHUTDOWN_F_STRING : "");
|
|
||||||
|
|
||||||
pstrcpy(shutdown_script, lp_shutdown_script());
|
|
||||||
|
|
||||||
if(*shutdown_script) {
|
|
||||||
int shutdown_ret;
|
|
||||||
all_string_sub(shutdown_script, "%m", chkmsg, sizeof(shutdown_script));
|
|
||||||
all_string_sub(shutdown_script, "%t", timeout, sizeof(shutdown_script));
|
|
||||||
all_string_sub(shutdown_script, "%r", r, sizeof(shutdown_script));
|
|
||||||
all_string_sub(shutdown_script, "%f", f, sizeof(shutdown_script));
|
|
||||||
shutdown_ret = smbrun(shutdown_script,NULL);
|
|
||||||
DEBUG(3,("_reg_shutdown: Running the command `%s' gave %d\n",shutdown_script,shutdown_ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
reg_abort_shutdwon
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u)
|
|
||||||
{
|
|
||||||
NTSTATUS status = NT_STATUS_OK;
|
|
||||||
pstring abort_shutdown_script;
|
|
||||||
|
|
||||||
pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
|
|
||||||
|
|
||||||
if(*abort_shutdown_script) {
|
|
||||||
int abort_shutdown_ret;
|
|
||||||
abort_shutdown_ret = smbrun(abort_shutdown_script,NULL);
|
|
||||||
DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",abort_shutdown_script,abort_shutdown_ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
REG_SAVE_KEY (0x14)
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u)
|
|
||||||
{
|
|
||||||
REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
|
|
||||||
|
|
||||||
DEBUG(5,("_reg_save_key: Enter\n"));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* basically this is a no op function which just gverifies
|
|
||||||
* that the client gave us a valid registry key handle
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( !regkey )
|
|
||||||
return NT_STATUS_INVALID_HANDLE;
|
|
||||||
|
|
||||||
DEBUG(8,("_reg_save_key: berifying backup of key [%s]\n", regkey->name));
|
|
||||||
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,437 +0,0 @@
|
|||||||
/*
|
|
||||||
Unix SMB/CIFS implementation.
|
|
||||||
SAMR Pipe utility functions.
|
|
||||||
|
|
||||||
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
|
|
||||||
Copyright (C) Gerald (Jerry) Carter 2000-2001
|
|
||||||
Copyright (C) Andrew Bartlett 2001-2002
|
|
||||||
Copyright (C) Stefan (metze) Metzmacher 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_SRV
|
|
||||||
|
|
||||||
#define STRING_CHANGED (old_string && !new_string) ||\
|
|
||||||
(!old_string && new_string) ||\
|
|
||||||
(old_string && new_string && (strcmp(old_string, new_string) != 0))
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Copies a SAM_USER_INFO_21 to a SAM_ACCOUNT
|
|
||||||
**************************************************************/
|
|
||||||
|
|
||||||
void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
|
|
||||||
{
|
|
||||||
time_t unix_time, stored_time;
|
|
||||||
const char *old_string, *new_string;
|
|
||||||
|
|
||||||
if (from == NULL || to == NULL)
|
|
||||||
return;
|
|
||||||
if (!nt_time_is_zero(&from->logon_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->logon_time);
|
|
||||||
stored_time = pdb_get_logon_time(to);
|
|
||||||
DEBUG(10,("INFO_21 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_logon_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
if (!nt_time_is_zero(&from->logoff_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->logoff_time);
|
|
||||||
stored_time = pdb_get_logoff_time(to);
|
|
||||||
DEBUG(10,("INFO_21 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->kickoff_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->kickoff_time);
|
|
||||||
stored_time = pdb_get_kickoff_time(to);
|
|
||||||
DEBUG(10,("INFO_21 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->pass_can_change_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_can_change_time);
|
|
||||||
stored_time = pdb_get_pass_can_change_time(to);
|
|
||||||
DEBUG(10,("INFO_21 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
if (!nt_time_is_zero(&from->pass_last_set_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_last_set_time);
|
|
||||||
stored_time = pdb_get_pass_last_set_time(to);
|
|
||||||
DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->pass_must_change_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_must_change_time);
|
|
||||||
stored_time=pdb_get_pass_must_change_time(to);
|
|
||||||
DEBUG(10,("INFO_21 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backend should check this for sainity */
|
|
||||||
if (from->hdr_user_name.buffer) {
|
|
||||||
old_string = pdb_get_username(to);
|
|
||||||
new_string = unistr2_static(&from->uni_user_name);
|
|
||||||
DEBUG(10,("INFO_21 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_username(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_full_name.buffer) {
|
|
||||||
old_string = pdb_get_fullname(to);
|
|
||||||
new_string = unistr2_static(&from->uni_full_name);
|
|
||||||
DEBUG(10,("INFO_21 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_fullname(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_home_dir.buffer) {
|
|
||||||
old_string = pdb_get_homedir(to);
|
|
||||||
new_string = unistr2_static(&from->uni_home_dir);
|
|
||||||
DEBUG(10,("INFO_21 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_homedir(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_dir_drive.buffer) {
|
|
||||||
old_string = pdb_get_dir_drive(to);
|
|
||||||
new_string = unistr2_static(&from->uni_dir_drive);
|
|
||||||
DEBUG(10,("INFO_21 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_dir_drive(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_logon_script.buffer) {
|
|
||||||
old_string = pdb_get_logon_script(to);
|
|
||||||
new_string = unistr2_static(&from->uni_logon_script);
|
|
||||||
DEBUG(10,("INFO_21 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_logon_script(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_profile_path.buffer) {
|
|
||||||
old_string = pdb_get_profile_path(to);
|
|
||||||
new_string = unistr2_static(&from->uni_profile_path);
|
|
||||||
DEBUG(10,("INFO_21 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_profile_path(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_acct_desc.buffer) {
|
|
||||||
old_string = pdb_get_acct_desc(to);
|
|
||||||
new_string = unistr2_static(&from->uni_acct_desc);
|
|
||||||
DEBUG(10,("INFO_21 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_acct_desc(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_workstations.buffer) {
|
|
||||||
old_string = pdb_get_workstations(to);
|
|
||||||
new_string = unistr2_static(&from->uni_workstations);
|
|
||||||
DEBUG(10,("INFO_21 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_workstations(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_unknown_str.buffer) {
|
|
||||||
old_string = pdb_get_unknown_str(to);
|
|
||||||
new_string = unistr2_static(&from->uni_unknown_str);
|
|
||||||
DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_unknown_str(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_munged_dial.buffer) {
|
|
||||||
old_string = pdb_get_munged_dial(to);
|
|
||||||
new_string = unistr2_static(&from->uni_munged_dial);
|
|
||||||
DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_munged_dial(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->user_rid != pdb_get_user_rid(to)) {
|
|
||||||
DEBUG(10,("INFO_21 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
|
|
||||||
/* we really allow this ??? metze */
|
|
||||||
/* pdb_set_user_sid_from_rid(to, from->user_rid, PDB_CHANGED);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->group_rid != pdb_get_group_rid(to)) {
|
|
||||||
DEBUG(10,("INFO_21 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
|
|
||||||
pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
|
|
||||||
if (from->acb_info != pdb_get_acct_ctrl(to)) {
|
|
||||||
pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 UNKOWN_3: %08X -> %08X\n",pdb_get_unknown_3(to),from->unknown_3));
|
|
||||||
if (from->unknown_3 != pdb_get_unknown_3(to)) {
|
|
||||||
pdb_set_unknown_3(to, from->unknown_3, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_21 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
|
|
||||||
if (from->logon_divs != pdb_get_logon_divs(to)) {
|
|
||||||
pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_21 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
|
|
||||||
if (from->logon_hrs.len != pdb_get_hours_len(to)) {
|
|
||||||
pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
|
|
||||||
/* Fix me: only update if it changes --metze */
|
|
||||||
pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 UNKOWN_5: %08X -> %08X\n",pdb_get_unknown_5(to),from->unknown_5));
|
|
||||||
if (from->unknown_5 != pdb_get_unknown_5(to)) {
|
|
||||||
pdb_set_unknown_5(to, from->unknown_5, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 UNKOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6));
|
|
||||||
if (from->unknown_6 != pdb_get_unknown_6(to)) {
|
|
||||||
pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 PADDING1 %02X %02X %02X %02X %02X %02X\n",
|
|
||||||
from->padding1[0],
|
|
||||||
from->padding1[1],
|
|
||||||
from->padding1[2],
|
|
||||||
from->padding1[3],
|
|
||||||
from->padding1[4],
|
|
||||||
from->padding1[5]));
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
|
|
||||||
if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) {
|
|
||||||
pdb_set_pass_must_change_time(to,0, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2));
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_21 PADDING_4: %08X\n",from->padding4));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
Copies a SAM_USER_INFO_23 to a SAM_ACCOUNT
|
|
||||||
**************************************************************/
|
|
||||||
|
|
||||||
void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
|
|
||||||
{
|
|
||||||
time_t unix_time, stored_time;
|
|
||||||
const char *old_string, *new_string;
|
|
||||||
|
|
||||||
if (from == NULL || to == NULL)
|
|
||||||
return;
|
|
||||||
if (!nt_time_is_zero(&from->logon_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->logon_time);
|
|
||||||
stored_time = pdb_get_logon_time(to);
|
|
||||||
DEBUG(10,("INFO_23 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_logon_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
if (!nt_time_is_zero(&from->logoff_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->logoff_time);
|
|
||||||
stored_time = pdb_get_logoff_time(to);
|
|
||||||
DEBUG(10,("INFO_23 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->kickoff_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->kickoff_time);
|
|
||||||
stored_time = pdb_get_kickoff_time(to);
|
|
||||||
DEBUG(10,("INFO_23 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->pass_can_change_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_can_change_time);
|
|
||||||
stored_time = pdb_get_pass_can_change_time(to);
|
|
||||||
DEBUG(10,("INFO_23 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
if (!nt_time_is_zero(&from->pass_last_set_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_last_set_time);
|
|
||||||
stored_time = pdb_get_pass_last_set_time(to);
|
|
||||||
DEBUG(10,("INFO_23 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nt_time_is_zero(&from->pass_must_change_time)) {
|
|
||||||
unix_time=nt_time_to_unix(&from->pass_must_change_time);
|
|
||||||
stored_time=pdb_get_pass_must_change_time(to);
|
|
||||||
DEBUG(10,("INFO_23 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
|
|
||||||
if (stored_time != unix_time)
|
|
||||||
pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Backend should check this for sainity */
|
|
||||||
if (from->hdr_user_name.buffer) {
|
|
||||||
old_string = pdb_get_username(to);
|
|
||||||
new_string = unistr2_static(&from->uni_user_name);
|
|
||||||
DEBUG(10,("INFO_23 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_username(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_full_name.buffer) {
|
|
||||||
old_string = pdb_get_fullname(to);
|
|
||||||
new_string = unistr2_static(&from->uni_full_name);
|
|
||||||
DEBUG(10,("INFO_23 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_fullname(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_home_dir.buffer) {
|
|
||||||
old_string = pdb_get_homedir(to);
|
|
||||||
new_string = unistr2_static(&from->uni_home_dir);
|
|
||||||
DEBUG(10,("INFO_23 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_homedir(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_dir_drive.buffer) {
|
|
||||||
old_string = pdb_get_dir_drive(to);
|
|
||||||
new_string = unistr2_static(&from->uni_dir_drive);
|
|
||||||
DEBUG(10,("INFO_23 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_dir_drive(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_logon_script.buffer) {
|
|
||||||
old_string = pdb_get_logon_script(to);
|
|
||||||
new_string = unistr2_static(&from->uni_logon_script);
|
|
||||||
DEBUG(10,("INFO_23 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_logon_script(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_profile_path.buffer) {
|
|
||||||
old_string = pdb_get_profile_path(to);
|
|
||||||
new_string = unistr2_static(&from->uni_profile_path);
|
|
||||||
DEBUG(10,("INFO_23 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_profile_path(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_acct_desc.buffer) {
|
|
||||||
old_string = pdb_get_acct_desc(to);
|
|
||||||
new_string = unistr2_static(&from->uni_acct_desc);
|
|
||||||
DEBUG(10,("INFO_23 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_acct_desc(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_workstations.buffer) {
|
|
||||||
old_string = pdb_get_workstations(to);
|
|
||||||
new_string = unistr2_static(&from->uni_workstations);
|
|
||||||
DEBUG(10,("INFO_23 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_workstations(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_unknown_str.buffer) {
|
|
||||||
old_string = pdb_get_unknown_str(to);
|
|
||||||
new_string = unistr2_static(&from->uni_unknown_str);
|
|
||||||
DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_unknown_str(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->hdr_munged_dial.buffer) {
|
|
||||||
old_string = pdb_get_munged_dial(to);
|
|
||||||
new_string = unistr2_static(&from->uni_munged_dial);
|
|
||||||
DEBUG(10,("INFO_23 UNI_MUNGED_DIAL: %s -> %s\n",old_string, new_string));
|
|
||||||
if (STRING_CHANGED)
|
|
||||||
pdb_set_munged_dial(to , new_string, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->user_rid != pdb_get_user_rid(to)) {
|
|
||||||
DEBUG(10,("INFO_23 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
|
|
||||||
/* we really allow this ??? metze */
|
|
||||||
/* pdb_set_user_sid_from_rid(to, from->user_rid, PDB_CHANGED);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from->group_rid != pdb_get_group_rid(to)) {
|
|
||||||
DEBUG(10,("INFO_23 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
|
|
||||||
pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
|
|
||||||
if (from->acb_info != pdb_get_acct_ctrl(to)) {
|
|
||||||
pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 UNKOWN_3: %08X -> %08X\n",pdb_get_unknown_3(to),from->unknown_3));
|
|
||||||
if (from->unknown_3 != pdb_get_unknown_3(to)) {
|
|
||||||
pdb_set_unknown_3(to, from->unknown_3, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_23 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
|
|
||||||
if (from->logon_divs != pdb_get_logon_divs(to)) {
|
|
||||||
pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_23 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
|
|
||||||
if (from->logon_hrs.len != pdb_get_hours_len(to)) {
|
|
||||||
pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(15,("INFO_23 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
|
|
||||||
/* Fix me: only update if it changes --metze */
|
|
||||||
pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 UNKOWN_5: %08X -> %08X\n",pdb_get_unknown_5(to),from->unknown_5));
|
|
||||||
if (from->unknown_5 != pdb_get_unknown_5(to)) {
|
|
||||||
pdb_set_unknown_5(to, from->unknown_5, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 UNKOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6));
|
|
||||||
if (from->unknown_6 != pdb_get_unknown_6(to)) {
|
|
||||||
pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 PADDING1 %02X %02X %02X %02X %02X %02X\n",
|
|
||||||
from->padding1[0],
|
|
||||||
from->padding1[1],
|
|
||||||
from->padding1[2],
|
|
||||||
from->padding1[3],
|
|
||||||
from->padding1[4],
|
|
||||||
from->padding1[5]));
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
|
|
||||||
if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) {
|
|
||||||
pdb_set_pass_must_change_time(to,0, PDB_CHANGED);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 PADDING_2: %02X\n",from->padding2));
|
|
||||||
|
|
||||||
DEBUG(10,("INFO_23 PADDING_4: %08X\n",from->padding4));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,557 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 2001,
|
|
||||||
* Copyright (C) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface to the srvsvc pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_srv_net_srv_get_info
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_srv_get_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SRV_GET_INFO q_u;
|
|
||||||
SRV_R_NET_SRV_GET_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net server get info */
|
|
||||||
if (!srv_io_q_net_srv_get_info("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _srv_net_srv_get_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if (!srv_io_r_net_srv_get_info("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_srv_net_srv_get_info
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_srv_set_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SRV_SET_INFO q_u;
|
|
||||||
SRV_R_NET_SRV_SET_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net server set info */
|
|
||||||
if (!srv_io_q_net_srv_set_info("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _srv_net_srv_set_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if (!srv_io_r_net_srv_set_info("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_srv_net_file_enum
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_file_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_FILE_ENUM q_u;
|
|
||||||
SRV_R_NET_FILE_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net file enum */
|
|
||||||
if (!srv_io_q_net_file_enum("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _srv_net_file_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!srv_io_r_net_file_enum("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_srv_net_conn_enum
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_conn_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_CONN_ENUM q_u;
|
|
||||||
SRV_R_NET_CONN_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net server get enum */
|
|
||||||
if (!srv_io_q_net_conn_enum("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _srv_net_conn_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if (!srv_io_r_net_conn_enum("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Enumerate sessions.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_sess_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SESS_ENUM q_u;
|
|
||||||
SRV_R_NET_SESS_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net server get enum */
|
|
||||||
if (!srv_io_q_net_sess_enum("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
/* construct reply. always indicate success */
|
|
||||||
r_u.status = _srv_net_sess_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if (!srv_io_r_net_sess_enum("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to enumerate shares.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_enum_all(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_ENUM q_u;
|
|
||||||
SRV_R_NET_SHARE_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server get enum. */
|
|
||||||
if(!srv_io_q_net_share_enum("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_enum_all: Failed to unmarshall SRV_Q_NET_SHARE_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_enum_all(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!srv_io_r_net_share_enum("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_enum_all: Failed to marshall SRV_R_NET_SHARE_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to enumerate shares.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_ENUM q_u;
|
|
||||||
SRV_R_NET_SHARE_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server get enum. */
|
|
||||||
if(!srv_io_q_net_share_enum("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_enum: Failed to unmarshall SRV_Q_NET_SHARE_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if (!srv_io_r_net_share_enum("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_enum: Failed to marshall SRV_R_NET_SHARE_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to return share information.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_get_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_GET_INFO q_u;
|
|
||||||
SRV_R_NET_SHARE_GET_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server get info. */
|
|
||||||
if(!srv_io_q_net_share_get_info("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_get_info: Failed to unmarshall SRV_Q_NET_SHARE_GET_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_get_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_share_get_info("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_get_info: Failed to marshall SRV_R_NET_SHARE_GET_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to set share information.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_set_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_SET_INFO q_u;
|
|
||||||
SRV_R_NET_SHARE_SET_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server set info. */
|
|
||||||
if(!srv_io_q_net_share_set_info("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_set_info: Failed to unmarshall SRV_Q_NET_SHARE_SET_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_set_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_share_set_info("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_set_info: Failed to marshall SRV_R_NET_SHARE_SET_INFO.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to add share information.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_add(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_ADD q_u;
|
|
||||||
SRV_R_NET_SHARE_ADD r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server add info. */
|
|
||||||
if(!srv_io_q_net_share_add("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_add: Failed to unmarshall SRV_Q_NET_SHARE_ADD.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_add(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_share_add("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_add: Failed to marshall SRV_R_NET_SHARE_ADD.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to delete share information.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_del(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_DEL q_u;
|
|
||||||
SRV_R_NET_SHARE_DEL r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server del info. */
|
|
||||||
if(!srv_io_q_net_share_del("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_del: Failed to unmarshall SRV_Q_NET_SHARE_DEL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_del(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_share_del("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_del: Failed to marshall SRV_R_NET_SHARE_DEL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to delete share information.
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_share_del_sticky(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_SHARE_DEL q_u;
|
|
||||||
SRV_R_NET_SHARE_DEL r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server del info. */
|
|
||||||
if(!srv_io_q_net_share_del("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_del_sticky: Failed to unmarshall SRV_Q_NET_SHARE_DEL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_share_del_sticky(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_share_del("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_share_del_sticky: Failed to marshall SRV_R_NET_SHARE_DEL.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_srv_net_remote_tod
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_remote_tod(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_REMOTE_TOD q_u;
|
|
||||||
SRV_R_NET_REMOTE_TOD r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net server get enum */
|
|
||||||
if(!srv_io_q_net_remote_tod("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _srv_net_remote_tod(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!srv_io_r_net_remote_tod("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
RPC to enumerate disks available on a server e.g. C:, D: ...
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_disk_enum(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_DISK_ENUM q_u;
|
|
||||||
SRV_R_NET_DISK_ENUM r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server disk enum. */
|
|
||||||
if(!srv_io_q_net_disk_enum("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_disk_enum: Failed to unmarshall SRV_Q_NET_DISK_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_disk_enum(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_disk_enum("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_disk_enum: Failed to marshall SRV_R_NET_DISK_ENUM.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
NetValidateName (opnum 0x21)
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_name_validate(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_NAME_VALIDATE q_u;
|
|
||||||
SRV_R_NET_NAME_VALIDATE r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net server disk enum. */
|
|
||||||
if(!srv_io_q_net_name_validate("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_name_validate: Failed to unmarshall SRV_Q_NET_NAME_VALIDATE.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_name_validate(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_name_validate("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_name_validate: Failed to marshall SRV_R_NET_NAME_VALIDATE.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
NetFileQuerySecdesc (opnum 0x27)
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_file_query_secdesc(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_FILE_QUERY_SECDESC q_u;
|
|
||||||
SRV_R_NET_FILE_QUERY_SECDESC r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net file get info from Win9x */
|
|
||||||
if(!srv_io_q_net_file_query_secdesc("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_file_query_secdesc: Failed to unmarshall SRV_Q_NET_FILE_QUERY_SECDESC.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_file_query_secdesc(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_file_query_secdesc("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_file_query_secdesc: Failed to marshall SRV_R_NET_FILE_QUERY_SECDESC.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
NetFileSetSecdesc (opnum 0x28)
|
|
||||||
*******************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
|
|
||||||
{
|
|
||||||
SRV_Q_NET_FILE_SET_SECDESC q_u;
|
|
||||||
SRV_R_NET_FILE_SET_SECDESC r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* Unmarshall the net file set info from Win9x */
|
|
||||||
if(!srv_io_q_net_file_set_secdesc("", &q_u, data, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_file_set_secdesc: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
r_u.status = _srv_net_file_set_secdesc(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
if(!srv_io_r_net_file_set_secdesc("", &r_u, rdata, 0)) {
|
|
||||||
DEBUG(0,("api_srv_net_file_set_secdesc: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n"));
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
\PIPE\srvsvc commands
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_SVC_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_srv_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static const struct api_struct api_srv_cmds[] =
|
|
||||||
{
|
|
||||||
{ "SRV_NET_CONN_ENUM" , SRV_NET_CONN_ENUM , api_srv_net_conn_enum },
|
|
||||||
{ "SRV_NET_SESS_ENUM" , SRV_NET_SESS_ENUM , api_srv_net_sess_enum },
|
|
||||||
{ "SRV_NET_SHARE_ENUM_ALL" , SRV_NET_SHARE_ENUM_ALL , api_srv_net_share_enum_all },
|
|
||||||
{ "SRV_NET_SHARE_ENUM" , SRV_NET_SHARE_ENUM , api_srv_net_share_enum },
|
|
||||||
{ "SRV_NET_SHARE_ADD" , SRV_NET_SHARE_ADD , api_srv_net_share_add },
|
|
||||||
{ "SRV_NET_SHARE_DEL" , SRV_NET_SHARE_DEL , api_srv_net_share_del },
|
|
||||||
{ "SRV_NET_SHARE_DEL_STICKY" , SRV_NET_SHARE_DEL_STICKY , api_srv_net_share_del_sticky },
|
|
||||||
{ "SRV_NET_SHARE_GET_INFO" , SRV_NET_SHARE_GET_INFO , api_srv_net_share_get_info },
|
|
||||||
{ "SRV_NET_SHARE_SET_INFO" , SRV_NET_SHARE_SET_INFO , api_srv_net_share_set_info },
|
|
||||||
{ "SRV_NET_FILE_ENUM" , SRV_NET_FILE_ENUM , api_srv_net_file_enum },
|
|
||||||
{ "SRV_NET_SRV_GET_INFO" , SRV_NET_SRV_GET_INFO , api_srv_net_srv_get_info },
|
|
||||||
{ "SRV_NET_SRV_SET_INFO" , SRV_NET_SRV_SET_INFO , api_srv_net_srv_set_info },
|
|
||||||
{ "SRV_NET_REMOTE_TOD" , SRV_NET_REMOTE_TOD , api_srv_net_remote_tod },
|
|
||||||
{ "SRV_NET_DISK_ENUM" , SRV_NET_DISK_ENUM , api_srv_net_disk_enum },
|
|
||||||
{ "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate },
|
|
||||||
{ "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc },
|
|
||||||
{ "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc }
|
|
||||||
};
|
|
||||||
return rpc_pipe_register_commands("srvsvc", "ntsvcs", api_srv_cmds,
|
|
||||||
sizeof(api_srv_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,546 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* this module apparently provides an implementation of DCE/RPC over a
|
|
||||||
* named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
|
|
||||||
* documentation are available (in on-line form) from the X-Open group.
|
|
||||||
*
|
|
||||||
* this module should provide a level of abstraction between SMB
|
|
||||||
* and DCE/RPC, while minimising the amount of mallocs, unnecessary
|
|
||||||
* data copies, and network traffic.
|
|
||||||
*
|
|
||||||
* in this version, which takes a "let's learn what's going on and
|
|
||||||
* get something running" approach, there is additional network
|
|
||||||
* traffic generated, but the code should be easier to understand...
|
|
||||||
*
|
|
||||||
* ... if you read the docs. or stare at packets for weeks on end.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A list of the rids of well known BUILTIN and Domain users
|
|
||||||
* and groups.
|
|
||||||
*/
|
|
||||||
|
|
||||||
rid_name builtin_alias_rids[] =
|
|
||||||
{
|
|
||||||
{ BUILTIN_ALIAS_RID_ADMINS , "Administrators" },
|
|
||||||
{ BUILTIN_ALIAS_RID_USERS , "Users" },
|
|
||||||
{ BUILTIN_ALIAS_RID_GUESTS , "Guests" },
|
|
||||||
{ BUILTIN_ALIAS_RID_POWER_USERS , "Power Users" },
|
|
||||||
|
|
||||||
{ BUILTIN_ALIAS_RID_ACCOUNT_OPS , "Account Operators" },
|
|
||||||
{ BUILTIN_ALIAS_RID_SYSTEM_OPS , "System Operators" },
|
|
||||||
{ BUILTIN_ALIAS_RID_PRINT_OPS , "Print Operators" },
|
|
||||||
{ BUILTIN_ALIAS_RID_BACKUP_OPS , "Backup Operators" },
|
|
||||||
{ BUILTIN_ALIAS_RID_REPLICATOR , "Replicator" },
|
|
||||||
{ 0 , NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* array lookup of well-known Domain RID users. */
|
|
||||||
rid_name domain_user_rids[] =
|
|
||||||
{
|
|
||||||
{ DOMAIN_USER_RID_ADMIN , "Administrator" },
|
|
||||||
{ DOMAIN_USER_RID_GUEST , "Guest" },
|
|
||||||
{ 0 , NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* array lookup of well-known Domain RID groups. */
|
|
||||||
rid_name domain_group_rids[] =
|
|
||||||
{
|
|
||||||
{ DOMAIN_GROUP_RID_ADMINS , "Domain Admins" },
|
|
||||||
{ DOMAIN_GROUP_RID_USERS , "Domain Users" },
|
|
||||||
{ DOMAIN_GROUP_RID_GUESTS , "Domain Guests" },
|
|
||||||
{ 0 , NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
gets a domain user's groups
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, uint32 **prids, DOM_SID *q_sid)
|
|
||||||
{
|
|
||||||
SAM_ACCOUNT *sam_pass=NULL;
|
|
||||||
int i, cur_rid=0;
|
|
||||||
gid_t gid;
|
|
||||||
gid_t *groups = NULL;
|
|
||||||
int num_groups;
|
|
||||||
GROUP_MAP map;
|
|
||||||
DOM_SID tmp_sid;
|
|
||||||
fstring user_name;
|
|
||||||
fstring str_domsid, str_qsid;
|
|
||||||
uint32 rid,grid;
|
|
||||||
uint32 *rids=NULL, *new_rids=NULL;
|
|
||||||
gid_t winbind_gid_low, winbind_gid_high;
|
|
||||||
BOOL ret;
|
|
||||||
BOOL winbind_groups_exist;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* this code is far from perfect.
|
|
||||||
* first it enumerates the full /etc/group and that can be slow.
|
|
||||||
* second, it works only with users' SIDs
|
|
||||||
* whereas the day we support nested groups, it will have to
|
|
||||||
* support both users's SIDs and domain groups' SIDs
|
|
||||||
*
|
|
||||||
* having our own ldap backend would be so much faster !
|
|
||||||
* we're far from that, but hope one day ;-) JFM.
|
|
||||||
*/
|
|
||||||
|
|
||||||
*prids=NULL;
|
|
||||||
*numgroups=0;
|
|
||||||
|
|
||||||
winbind_groups_exist = lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
|
|
||||||
|
|
||||||
|
|
||||||
DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n",
|
|
||||||
sid_to_string(str_qsid, q_sid), sid_to_string(str_domsid, sid)));
|
|
||||||
|
|
||||||
pdb_init_sam(&sam_pass);
|
|
||||||
become_root();
|
|
||||||
ret = pdb_getsampwsid(sam_pass, q_sid);
|
|
||||||
unbecome_root();
|
|
||||||
if (ret == False) {
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
return NT_STATUS_NO_SUCH_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
fstrcpy(user_name, pdb_get_username(sam_pass));
|
|
||||||
grid=pdb_get_group_rid(sam_pass);
|
|
||||||
gid=pdb_get_gid(sam_pass);
|
|
||||||
|
|
||||||
become_root();
|
|
||||||
/* on some systems this must run as root */
|
|
||||||
num_groups = getgroups_user(user_name, &groups);
|
|
||||||
unbecome_root();
|
|
||||||
if (num_groups == -1) {
|
|
||||||
/* this should never happen */
|
|
||||||
DEBUG(2,("get_alias_user_groups: getgroups_user failed\n"));
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
return NT_STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0;i<num_groups;i++) {
|
|
||||||
if(!get_group_from_gid(groups[i], &map, MAPPING_WITHOUT_PRIV)) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i]));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if it's not an alias, continue */
|
|
||||||
if (map.sid_name_use!=SID_NAME_ALIAS) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sid_copy(&tmp_sid, &map.sid);
|
|
||||||
sid_split_rid(&tmp_sid, &rid);
|
|
||||||
|
|
||||||
/* if the sid is not in the correct domain, continue */
|
|
||||||
if (!sid_equal(&tmp_sid, sid)) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't return winbind groups as they are not local! */
|
|
||||||
if (winbind_groups_exist && (groups[i] >= winbind_gid_low) && (groups[i] <= winbind_gid_high)) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't return user private groups... */
|
|
||||||
if (Get_Pwnam(map.nt_name) != 0) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
|
|
||||||
if (new_rids==NULL) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
free(groups);
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
rids=new_rids;
|
|
||||||
|
|
||||||
sid_peek_rid(&map.sid, &(rids[cur_rid]));
|
|
||||||
cur_rid++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(groups);
|
|
||||||
|
|
||||||
/* now check for the user's gid (the primary group rid) */
|
|
||||||
for (i=0; i<cur_rid && grid!=rids[i]; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* the user's gid is already there */
|
|
||||||
if (i!=cur_rid) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n"));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name));
|
|
||||||
|
|
||||||
if(!get_group_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) {
|
|
||||||
DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your /etc/passwd and /etc/group files\n", user_name));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the primary group isn't an alias */
|
|
||||||
if (map.sid_name_use!=SID_NAME_ALIAS) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
sid_copy(&tmp_sid, &map.sid);
|
|
||||||
sid_split_rid(&tmp_sid, &rid);
|
|
||||||
|
|
||||||
/* if the sid is not in the correct domain, continue */
|
|
||||||
if (!sid_equal(&tmp_sid, sid)) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map.nt_name));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't return winbind groups as they are not local! */
|
|
||||||
if (winbind_groups_exist && (gid >= winbind_gid_low) && (gid <= winbind_gid_high)) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name ));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't return user private groups... */
|
|
||||||
if (Get_Pwnam(map.nt_name) != 0) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map.nt_name ));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_rids=(uint32 *)Realloc(rids, sizeof(uint32)*(cur_rid+1));
|
|
||||||
if (new_rids==NULL) {
|
|
||||||
DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
rids=new_rids;
|
|
||||||
|
|
||||||
sid_peek_rid(&map.sid, &(rids[cur_rid]));
|
|
||||||
cur_rid++;
|
|
||||||
|
|
||||||
done:
|
|
||||||
*prids=rids;
|
|
||||||
*numgroups=cur_rid;
|
|
||||||
pdb_free_sam(&sam_pass);
|
|
||||||
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
gets a domain user's groups
|
|
||||||
********************************************************************/
|
|
||||||
BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SAM_ACCOUNT *sam_pass)
|
|
||||||
{
|
|
||||||
GROUP_MAP *map=NULL;
|
|
||||||
int i, num, num_entries, cur_gid=0;
|
|
||||||
struct group *grp;
|
|
||||||
DOM_GID *gids;
|
|
||||||
fstring user_name;
|
|
||||||
uint32 grid;
|
|
||||||
uint32 tmp_rid;
|
|
||||||
|
|
||||||
*numgroups= 0;
|
|
||||||
|
|
||||||
fstrcpy(user_name, pdb_get_username(sam_pass));
|
|
||||||
grid=pdb_get_group_rid(sam_pass);
|
|
||||||
|
|
||||||
DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name));
|
|
||||||
|
|
||||||
/* first get the list of the domain groups */
|
|
||||||
if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
|
|
||||||
return False;
|
|
||||||
DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* alloc memory. In the worse case, we alloc memory for nothing.
|
|
||||||
* but I prefer to alloc for nothing
|
|
||||||
* than reallocing everytime.
|
|
||||||
*/
|
|
||||||
gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) * num_entries);
|
|
||||||
|
|
||||||
/* for each group, check if the user is a member of*/
|
|
||||||
for(i=0; i<num_entries; i++) {
|
|
||||||
if ((grp=getgrgid(map[i].gid)) == NULL) {
|
|
||||||
/* very weird !!! */
|
|
||||||
DEBUG(5,("get_domain_user_groups: gid %d doesn't exist anymore !\n", (int)map[i].gid));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(num=0; grp->gr_mem[num]!=NULL; num++) {
|
|
||||||
if(strcmp(grp->gr_mem[num], user_name)==0) {
|
|
||||||
/* we found the user, add the group to the list */
|
|
||||||
sid_peek_rid(&map[i].sid, &(gids[cur_gid].g_rid));
|
|
||||||
gids[cur_gid].attr=7;
|
|
||||||
DEBUG(10,("get_domain_user_groups: user found in group %s\n", map[i].nt_name));
|
|
||||||
cur_gid++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we have checked the groups */
|
|
||||||
/* we must now check the gid of the user or the primary group rid, that's the same */
|
|
||||||
for (i=0; i<cur_gid && grid!=gids[i].g_rid; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
/* the user's gid is already there */
|
|
||||||
if (i!=cur_gid) {
|
|
||||||
/*
|
|
||||||
* the primary group of the user but be the first one in the list
|
|
||||||
* don't ask ! JFM.
|
|
||||||
*/
|
|
||||||
gids[i].g_rid=gids[0].g_rid;
|
|
||||||
gids[0].g_rid=grid;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0; i<num_entries; i++) {
|
|
||||||
sid_peek_rid(&map[i].sid, &tmp_rid);
|
|
||||||
if (tmp_rid==grid) {
|
|
||||||
/*
|
|
||||||
* the primary group of the user but be the first one in the list
|
|
||||||
* don't ask ! JFM.
|
|
||||||
*/
|
|
||||||
gids[cur_gid].g_rid=gids[0].g_rid;
|
|
||||||
gids[0].g_rid=tmp_rid;
|
|
||||||
gids[cur_gid].attr=7;
|
|
||||||
DEBUG(10,("get_domain_user_groups: primary gid of user found in group %s\n", map[i].nt_name));
|
|
||||||
cur_gid++;
|
|
||||||
goto done; /* leave the loop early */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(0,("get_domain_user_groups: primary gid of user [%s] is not a Domain group !\n", user_name));
|
|
||||||
DEBUGADD(0,("get_domain_user_groups: You should fix it, NT doesn't like that\n"));
|
|
||||||
|
|
||||||
|
|
||||||
done:
|
|
||||||
*pgids=gids;
|
|
||||||
*numgroups=cur_gid;
|
|
||||||
safe_free(map);
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
gets a domain user's groups from their already-calculated NT_USER_TOKEN
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
|
|
||||||
const NT_USER_TOKEN *nt_token,
|
|
||||||
int *numgroups, DOM_GID **pgids)
|
|
||||||
{
|
|
||||||
DOM_GID *gids;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
gids = (DOM_GID *)talloc(mem_ctx, sizeof(*gids) * nt_token->num_sids);
|
|
||||||
|
|
||||||
if (!gids) {
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
*numgroups=0;
|
|
||||||
|
|
||||||
for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) {
|
|
||||||
if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) {
|
|
||||||
sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid));
|
|
||||||
gids[*numgroups].attr=7;
|
|
||||||
(*numgroups)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pgids = gids;
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local (domain) rid and return a name and type.
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_group_name(uint32 rid, char *group_name, uint32 *type)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
(*type) = SID_NAME_DOM_GRP;
|
|
||||||
|
|
||||||
DEBUG(5,("lookup_group_name: rid: %d", rid));
|
|
||||||
|
|
||||||
while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain_group_rids[i].rid != 0)
|
|
||||||
{
|
|
||||||
fstrcpy(group_name, domain_group_rids[i].name);
|
|
||||||
DEBUG(5,(" = %s\n", group_name));
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(5,(" none mapped\n"));
|
|
||||||
return NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local alias rid and return a name and type.
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
(*type) = SID_NAME_WKN_GRP;
|
|
||||||
|
|
||||||
DEBUG(5,("lookup_alias_name: rid: %d", rid));
|
|
||||||
|
|
||||||
while (builtin_alias_rids[i].rid != rid && builtin_alias_rids[i].rid != 0)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builtin_alias_rids[i].rid != 0)
|
|
||||||
{
|
|
||||||
fstrcpy(alias_name, builtin_alias_rids[i].name);
|
|
||||||
DEBUG(5,(" = %s\n", alias_name));
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(5,(" none mapped\n"));
|
|
||||||
return NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0 /*Nobody uses this function just now*/
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local user rid and return a name and type.
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_user_name(uint32 rid, char *user_name, uint32 *type)
|
|
||||||
{
|
|
||||||
SAM_ACCOUNT *sampwd=NULL;
|
|
||||||
int i = 0;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
(*type) = SID_NAME_USER;
|
|
||||||
|
|
||||||
DEBUG(5,("lookup_user_name: rid: %d", rid));
|
|
||||||
|
|
||||||
/* look up the well-known domain user rids first */
|
|
||||||
while (domain_user_rids[i].rid != rid && domain_user_rids[i].rid != 0)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain_user_rids[i].rid != 0) {
|
|
||||||
fstrcpy(user_name, domain_user_rids[i].name);
|
|
||||||
DEBUG(5,(" = %s\n", user_name));
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdb_init_sam(&sampwd);
|
|
||||||
|
|
||||||
/* ok, it's a user. find the user account */
|
|
||||||
become_root();
|
|
||||||
ret = pdb_getsampwrid(sampwd, rid);
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
if (ret == True) {
|
|
||||||
fstrcpy(user_name, pdb_get_username(sampwd) );
|
|
||||||
DEBUG(5,(" = %s\n", user_name));
|
|
||||||
pdb_free_sam(&sampwd);
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG(5,(" none mapped\n"));
|
|
||||||
pdb_free_sam(&sampwd);
|
|
||||||
return NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local (domain) group name and return a rid
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_group_rid(char *group_name, uint32 *rid)
|
|
||||||
{
|
|
||||||
const char *grp_name;
|
|
||||||
int i = -1; /* start do loop at -1 */
|
|
||||||
|
|
||||||
do /* find, if it exists, a group rid for the group name*/
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
(*rid) = domain_group_rids[i].rid;
|
|
||||||
grp_name = domain_group_rids[i].name;
|
|
||||||
|
|
||||||
} while (grp_name != NULL && !strequal(grp_name, group_name));
|
|
||||||
|
|
||||||
return (grp_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local (BUILTIN) alias name and return a rid
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_alias_rid(const char *alias_name, uint32 *rid)
|
|
||||||
{
|
|
||||||
const char *als_name;
|
|
||||||
int i = -1; /* start do loop at -1 */
|
|
||||||
|
|
||||||
do /* find, if it exists, a alias rid for the alias name*/
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
(*rid) = builtin_alias_rids[i].rid;
|
|
||||||
als_name = builtin_alias_rids[i].name;
|
|
||||||
|
|
||||||
} while (als_name != NULL && !strequal(als_name, alias_name));
|
|
||||||
|
|
||||||
return (als_name != NULL) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
Look up a local user name and return a rid
|
|
||||||
********************************************************************/
|
|
||||||
NTSTATUS local_lookup_user_rid(char *user_name, uint32 *rid)
|
|
||||||
{
|
|
||||||
SAM_ACCOUNT *sampass=NULL;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
(*rid) = 0;
|
|
||||||
|
|
||||||
pdb_init_sam(&sampass);
|
|
||||||
|
|
||||||
/* find the user account */
|
|
||||||
become_root();
|
|
||||||
ret = pdb_getsampwnam(sampass, user_name);
|
|
||||||
unbecome_root();
|
|
||||||
|
|
||||||
if (ret == True) {
|
|
||||||
(*rid) = pdb_get_user_rid(sampass);
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdb_free_sam(&sampass);
|
|
||||||
return NT_STATUS_NONE_MAPPED;
|
|
||||||
}
|
|
@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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) Anthony Liguori 2003.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the interface to the wks pipe. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
api_wks_query_info
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static BOOL api_wks_query_info(pipes_struct *p)
|
|
||||||
{
|
|
||||||
WKS_Q_QUERY_INFO q_u;
|
|
||||||
WKS_R_QUERY_INFO r_u;
|
|
||||||
prs_struct *data = &p->in_data.data;
|
|
||||||
prs_struct *rdata = &p->out_data.rdata;
|
|
||||||
|
|
||||||
ZERO_STRUCT(q_u);
|
|
||||||
ZERO_STRUCT(r_u);
|
|
||||||
|
|
||||||
/* grab the net share enum */
|
|
||||||
if(!wks_io_q_query_info("", &q_u, data, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
r_u.status = _wks_query_info(p, &q_u, &r_u);
|
|
||||||
|
|
||||||
/* store the response in the SMB stream */
|
|
||||||
if(!wks_io_r_query_info("", &r_u, rdata, 0))
|
|
||||||
return False;
|
|
||||||
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
\PIPE\wkssvc commands
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
#ifdef RPC_WKS_DYNAMIC
|
|
||||||
int init_module(void)
|
|
||||||
#else
|
|
||||||
int rpc_wks_init(void)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static struct api_struct api_wks_cmds[] =
|
|
||||||
{
|
|
||||||
{ "WKS_Q_QUERY_INFO", WKS_QUERY_INFO, api_wks_query_info }
|
|
||||||
};
|
|
||||||
return rpc_pipe_register_commands("wkssvc", "ntsvcs", api_wks_cmds,
|
|
||||||
sizeof(api_wks_cmds) / sizeof(struct api_struct));
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* This is the implementation of the wks interface. */
|
|
||||||
|
|
||||||
#include "includes.h"
|
|
||||||
|
|
||||||
#undef DBGC_CLASS
|
|
||||||
#define DBGC_CLASS DBGC_RPC_SRV
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
create_wks_info_100
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
static void create_wks_info_100(WKS_INFO_100 *inf)
|
|
||||||
{
|
|
||||||
pstring my_name;
|
|
||||||
pstring domain;
|
|
||||||
|
|
||||||
DEBUG(5,("create_wks_info_100: %d\n", __LINE__));
|
|
||||||
|
|
||||||
pstrcpy (my_name, lp_netbios_name());
|
|
||||||
strupper(my_name);
|
|
||||||
|
|
||||||
pstrcpy (domain, lp_workgroup());
|
|
||||||
strupper(domain);
|
|
||||||
|
|
||||||
init_wks_info_100(inf,
|
|
||||||
0x000001f4, /* platform id info */
|
|
||||||
lp_major_announce_version(),
|
|
||||||
lp_minor_announce_version(),
|
|
||||||
my_name, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
wks_reply_query_info
|
|
||||||
|
|
||||||
only supports info level 100 at the moment.
|
|
||||||
|
|
||||||
********************************************************************/
|
|
||||||
|
|
||||||
NTSTATUS _wks_query_info(pipes_struct *p, WKS_Q_QUERY_INFO *q_u, WKS_R_QUERY_INFO *r_u)
|
|
||||||
{
|
|
||||||
WKS_INFO_100 *wks100 = NULL;
|
|
||||||
|
|
||||||
DEBUG(5,("_wks_query_info: %d\n", __LINE__));
|
|
||||||
|
|
||||||
wks100 = (WKS_INFO_100 *)talloc_zero(p->mem_ctx, sizeof(WKS_INFO_100));
|
|
||||||
|
|
||||||
if (!wks100)
|
|
||||||
return NT_STATUS_NO_MEMORY;
|
|
||||||
|
|
||||||
create_wks_info_100(wks100);
|
|
||||||
init_wks_r_query_info(r_u, q_u->switch_value, wks100, NT_STATUS_OK);
|
|
||||||
|
|
||||||
DEBUG(5,("_wks_query_info: %d\n", __LINE__));
|
|
||||||
|
|
||||||
return r_u->status;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user