summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-07-15 10:35:28 +0000
committerAndrew Tridgell <tridge@samba.org>2002-07-15 10:35:28 +0000
commite90b65284812aaa5ff9e9935ce9bbad7791cbbcd (patch)
tree9e744d1dc2f93934a4b49166a37383d3cb2b2139 /source3/rpc_server
parentec167dc9cc0ec2ee461837c25a371d2981744208 (diff)
downloadsamba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.gz
samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.tar.bz2
samba-e90b65284812aaa5ff9e9935ce9bbad7791cbbcd.zip
updated the 3.0 branch from the head branch - ready for alpha18
(This used to be commit 03ac082dcb375b6f3ca3d810a6a6367542bc23ce)
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_dfs.c3
-rw-r--r--source3/rpc_server/srv_dfs_nt.c33
-rw-r--r--source3/rpc_server/srv_lsa.c5
-rw-r--r--source3/rpc_server/srv_lsa_hnd.c48
-rw-r--r--source3/rpc_server/srv_lsa_nt.c58
-rw-r--r--source3/rpc_server/srv_netlog.c3
-rw-r--r--source3/rpc_server/srv_netlog_nt.c53
-rw-r--r--source3/rpc_server/srv_pipe.c7
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c50
-rw-r--r--source3/rpc_server/srv_reg.c138
-rw-r--r--source3/rpc_server/srv_reg_nt.c661
-rw-r--r--source3/rpc_server/srv_samr.c35
-rw-r--r--source3/rpc_server/srv_samr_nt.c1339
-rwxr-xr-xsource3/rpc_server/srv_spoolss.c125
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c1330
-rw-r--r--source3/rpc_server/srv_srvsvc.c39
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c143
-rw-r--r--source3/rpc_server/srv_util.c18
-rw-r--r--source3/rpc_server/srv_wkssvc.c5
-rw-r--r--source3/rpc_server/srv_wkssvc_nt.c3
20 files changed, 3058 insertions, 1038 deletions
diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c
index 4351fd088e..5edc1222a8 100644
--- a/source3/rpc_server/srv_dfs.c
+++ b/source3/rpc_server/srv_dfs.c
@@ -28,6 +28,9 @@
#define MAX_MSDFS_JUNCTIONS 256
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
/**********************************************************************
diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c
index 4db6c61a3c..65e387176d 100644
--- a/source3/rpc_server/srv_dfs_nt.c
+++ b/source3/rpc_server/srv_dfs_nt.c
@@ -26,6 +26,9 @@
#include "includes.h"
#include "nterr.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
#define MAX_MSDFS_JUNCTIONS 256
@@ -69,10 +72,7 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
pstrcat(altpath, "\\");
pstrcat(altpath, sharename);
- if(!create_junction(dfspath, &jn))
- return WERR_DFS_NO_SUCH_SERVER;
-
- if(get_referred_path(&jn))
+ if(get_referred_path(dfspath, &jn, NULL, NULL))
{
exists = True;
jn.referral_count += 1;
@@ -137,16 +137,14 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
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(!create_junction(dfspath, &jn))
- return WERR_DFS_NO_SUCH_SERVER;
-
- if(!get_referred_path(&jn))
- return WERR_DFS_NO_SUCH_VOL;
+ 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)
@@ -158,14 +156,18 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
{
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;
}
}
@@ -227,8 +229,13 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_I
{
pstring str;
dfs3[i].ptr_entrypath = 1;
- slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname,
- j[i].service_name, j[i].volume_name);
+ if (j[i].volume_name[0] == '\0')
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
+ global_myname, j[i].service_name);
+ else
+ slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname,
+ 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);
@@ -355,8 +362,8 @@ WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
if(!create_junction(path, &jn))
return WERR_DFS_NO_SUCH_SERVER;
- if(!get_referred_path(&jn))
- return WERR_DFS_NO_SUCH_VOL;
+ if(!get_referred_path(path, &jn, NULL, NULL))
+ return WERR_DFS_NO_SUCH_VOL;
r_u->level = level;
r_u->ptr_ctr = 1;
diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c
index fcd4be0212..e5a4d3b46d 100644
--- a/source3/rpc_server/srv_lsa.c
+++ b/source3/rpc_server/srv_lsa.c
@@ -25,6 +25,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/***************************************************************************
api_lsa_open_policy2
***************************************************************************/
@@ -105,8 +108,10 @@ static BOOL api_lsa_enum_trust_dom(pipes_struct *p)
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;
diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c
index 84c3c5a959..2d04d72323 100644
--- a/source3/rpc_server/srv_lsa_hnd.c
+++ b/source3/rpc_server/srv_lsa_hnd.c
@@ -22,6 +22,9 @@
#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
@@ -134,6 +137,14 @@ BOOL create_policy_hnd(pipes_struct *p, POLICY_HND *hnd, void (*free_fn)(void *)
DLIST_ADD(p->pipe_handles->Policy, pol);
p->pipe_handles->count++;
+ /*
+ * Ensure we don't idle this connection if a handle is open.
+ * Increment the number of files open on the first handle create.
+ */
+
+ if (p->pipe_handles->count == 1)
+ p->conn->num_files_open++;
+
*hnd = pol->pol_hnd;
DEBUG(4,("Opened policy hnd[%d] ", (int)p->pipe_handles->count));
@@ -201,6 +212,15 @@ BOOL close_policy_hnd(pipes_struct *p, POLICY_HND *hnd)
p->pipe_handles->count--;
+ /*
+ * Ensure we can idle this connection if this is the last handle.
+ * Decrement the number of files open on the last handle delete.
+ */
+
+ if (p->pipe_handles->count == 0)
+ p->conn->num_files_open--;
+
+
DLIST_REMOVE(p->pipe_handles->Policy, pol);
ZERO_STRUCTP(pol);
@@ -232,3 +252,31 @@ void close_policy_by_pipe(pipes_struct *p)
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;
+}
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index 84ab44bc30..d072061a5f 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -3,8 +3,9 @@
* 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) Paul Ashton 1997,
+ * Copyright (C) Jeremy Allison 2001,
+ * Copyright (C) Rafal Szczesniak 2002.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +26,9 @@
#include "includes.h"
-extern DOM_SID global_sam_sid;
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern fstring global_myworkgroup;
extern pstring global_myname;
extern PRIVS privs[];
@@ -164,7 +167,7 @@ static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" :
"not found"));
- if (status) {
+ if (status && name_type != SID_NAME_UNKNOWN) {
sid_split_rid(&sid, &rid);
dom_idx = init_dom_ref(ref, dom_name, &sid);
(*mapped_count)++;
@@ -258,6 +261,8 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME
if (!status) {
sid_name_use = SID_NAME_UNKNOWN;
+ } else {
+ (*mapped_count)++;
}
/* Store domain sid in ref array */
@@ -271,8 +276,6 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME
DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to "
"referenced list.\n", dom_name, name ));
- (*mapped_count)++;
-
init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
sid_name_use, name, dom_idx);
total++;
@@ -319,7 +322,7 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s
init_sec_access(&mask, POLICY_EXECUTE);
init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- sid_copy(&adm_sid, &global_sam_sid);
+ sid_copy(&adm_sid, get_global_sam_sid());
sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
init_sec_access(&mask, POLICY_ALL_ACCESS);
init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
@@ -366,7 +369,7 @@ NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL
return NT_STATUS_NO_MEMORY;
ZERO_STRUCTP(info);
- info->sid = global_sam_sid;
+ sid_copy(&info->sid,get_global_sam_sid());
info->access = acc_granted;
/* set up the LSA QUERY INFO response */
@@ -404,7 +407,7 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *
return NT_STATUS_NO_MEMORY;
ZERO_STRUCTP(info);
- info->sid = global_sam_sid;
+ sid_copy(&info->sid,get_global_sam_sid());
info->access = acc_granted;
/* set up the LSA QUERY INFO response */
@@ -416,14 +419,22 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *
/***************************************************************************
_lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
+ ufff, done :) mimir
***************************************************************************/
NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
{
struct lsa_info *info;
- uint32 enum_context = 0;
- char *dom_name = NULL;
- DOM_SID *dom_sid = NULL;
+ uint32 enum_context = q_u->enum_context;
+
+ /*
+ * preferred length is set to 5 as a "our" preferred length
+ * nt sets this parameter to 2
+ */
+ uint32 max_num_domains = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
+ TRUSTDOM **trust_doms;
+ uint32 num_domains;
+ NTSTATUS nt_status;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
@@ -432,9 +443,18 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- /* set up the LSA QUERY INFO response */
- init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, dom_name, dom_sid,
- dom_name != NULL ? NT_STATUS_OK : NT_STATUS_NO_MORE_ENTRIES);
+ nt_status = secrets_get_trusted_domains(p->mem_ctx, &enum_context, max_num_domains, &num_domains, &trust_doms);
+
+ if (!NT_STATUS_IS_OK(nt_status) &&
+ !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
+ return nt_status;
+ } else {
+ r_u->status = nt_status;
+ }
+
+ /* set up the lsa_enum_trust_dom response */
+ init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms);
return r_u->status;
}
@@ -484,7 +504,7 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
name = global_myworkgroup;
- sid = &global_sam_sid;
+ sid = get_global_sam_sid();
break;
case ROLE_DOMAIN_MEMBER:
name = global_myworkgroup;
@@ -514,15 +534,15 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
name = global_myworkgroup;
- sid = &global_sam_sid;
+ sid = get_global_sam_sid();
break;
case ROLE_DOMAIN_MEMBER:
name = global_myname;
- sid = &global_sam_sid;
+ sid = get_global_sam_sid();
break;
case ROLE_STANDALONE:
name = global_myname;
- sid = &global_sam_sid;
+ sid = get_global_sam_sid();
break;
default:
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c
index dfd270ff7d..f96a0e2f2d 100644
--- a/source3/rpc_server/srv_netlog.c
+++ b/source3/rpc_server/srv_netlog.c
@@ -25,6 +25,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/*************************************************************************
api_net_req_chal:
*************************************************************************/
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index bdb064c81d..4ab9c470d0 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -26,8 +26,10 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
-extern DOM_SID global_sam_sid;
/*************************************************************************
init_net_r_req_chal:
@@ -150,7 +152,7 @@ NTSTATUS _net_trust_dom_list(pipes_struct *p, NET_Q_TRUST_DOM_LIST *q_u, NET_R_T
***********************************************************************************/
static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
- DOM_CRED *srv_cred, NTSTATUS status)
+ DOM_CRED *srv_cred, NTSTATUS status)
{
DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
@@ -378,7 +380,7 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
{
- NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
+ NTSTATUS status = NT_STATUS_ACCESS_DENIED;
DOM_CRED srv_cred;
pstring workstation;
SAM_ACCOUNT *sampass=NULL;
@@ -395,8 +397,8 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
- rpcstr_pull(workstation,q_u->clnt_id.login.uni_acct_name.buffer,
- sizeof(workstation),q_u->clnt_id.login.uni_acct_name.uni_str_len*2,0);
+ 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));
@@ -656,14 +658,35 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
{
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;
- pstring my_workgroup;
-
+ fstring user_sid_string;
+ fstring group_sid_string;
+
+ sampw = server_info->sam_account;
+
/* set up pointer indicating user/password failed to be found */
usr_info->ptr_user_info = 0;
-
- pstrcpy(my_workgroup, lp_workgroup());
+
+ 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, global_myname);
strupper(my_name);
@@ -677,12 +700,10 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
gids = NULL;
get_domain_user_groups(p->mem_ctx, &num_gids, &gids, server_info->sam_account);
-
- sampw = server_info->sam_account;
init_net_user_info3(p->mem_ctx, usr_info,
- pdb_get_user_rid(sampw),
- pdb_get_group_rid(sampw),
+ user_rid,
+ group_rid,
pdb_get_username(sampw),
pdb_get_fullname(sampw),
@@ -704,8 +725,10 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
0x20 , /* uint32 user_flgs (?) */
NULL, /* uchar sess_key[16] */
my_name , /* char *logon_srv */
- my_workgroup, /* char *logon_dom */
- &global_sam_sid, /* DOM_SID *dom_sid */
+ pdb_get_domain(sampw),
+ &domain_sid, /* DOM_SID *dom_sid */
+ /* Should be users domain sid, not servers - for trusted domains */
+
NULL); /* char *other_sids */
}
free_server_info(&server_info);
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 70574b4cdd..b7be415abc 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -39,6 +39,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
static void NTLMSSPcalc_p( pipes_struct *p, unsigned char *data, int len)
{
unsigned char *hash = p->ntlmssp_hash;
@@ -432,7 +435,7 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name ));
/* Set up pipe user group membership. */
initialise_groups(p->pipe_user_name, p->pipe_user.uid, p->pipe_user.gid);
- get_current_groups( &p->pipe_user.ngroups, &p->pipe_user.groups);
+ get_current_groups(p->pipe_user.gid, &p->pipe_user.ngroups, &p->pipe_user.groups);
if (server_info->ptok)
add_supplementary_nt_login_groups(&p->pipe_user.ngroups, &p->pipe_user.groups, &server_info->ptok);
@@ -1148,7 +1151,7 @@ BOOL api_pipe_request(pipes_struct *p)
********************************************************************/
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name,
- struct api_struct *api_rpc_cmds)
+ const struct api_struct *api_rpc_cmds)
{
int fn_num;
fstring name;
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 44dd5fac65..cc6e4b95f9 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -22,6 +22,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
#define PIPE "\\PIPE\\"
#define PIPELEN strlen(PIPE)
@@ -32,6 +35,23 @@ static int pipes_open;
#define MAX_OPEN_PIPES 2048
#endif
+/*
+ * Sometimes I can't decide if I hate Windows printer driver
+ * writers more than I hate the Windows spooler service driver
+ * writers. This gets around a combination of bugs in the spooler
+ * and the HP 8500 PCL driver that causes a spooler spin. JRA.
+ *
+ * bumped up from 20 -> 64 after viewing traffic from WordPerfect
+ * 2002 running on NT 4.- SP6
+ * bumped up from 64 -> 256 after viewing traffic from con2prt
+ * for lots of printers on a WinNT 4.x SP6 box.
+ */
+
+#ifndef MAX_OPEN_SPOOLSS_PIPES
+#define MAX_OPEN_SPOOLSS_PIPES 256
+#endif
+static int current_spoolss_pipes_open;
+
static smb_np_struct *Pipes;
static pipes_struct *InternalPipes;
static struct bitmap *bmap;
@@ -99,6 +119,7 @@ void set_pipe_handle_offset(int max_open_files)
/****************************************************************************
Reset pipe chain handle number.
****************************************************************************/
+
void reset_chain_p(void)
{
chain_p = NULL;
@@ -155,11 +176,20 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
int i;
smb_np_struct *p, *p_it;
static int next_pipe;
+ BOOL is_spoolss_pipe = False;
DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
pipe_name, pipes_open));
-
+ if (strstr(pipe_name, "spoolss"))
+ is_spoolss_pipe = True;
+
+ if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) {
+ DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n",
+ pipe_name ));
+ return NULL;
+ }
+
/* not repeating pipe numbers makes it easier to track things in
log files and prevents client bugs where pipe numbers are reused
over connection restarts */
@@ -180,8 +210,7 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
p = (smb_np_struct *)malloc(sizeof(*p));
- if (!p)
- {
+ if (!p) {
DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
return NULL;
}
@@ -198,13 +227,11 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
p->np_state = p->namedpipe_create(pipe_name, conn, vuid);
if (p->np_state == NULL) {
-
DEBUG(0,("open_rpc_pipe_p: make_internal_rpc_pipe_p failed.\n"));
SAFE_FREE(p);
return NULL;
}
-
DLIST_ADD(Pipes, p);
/*
@@ -244,7 +271,7 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
}
/****************************************************************************
- * make an internal namedpipes structure
+ Make an internal namedpipes structure
****************************************************************************/
static void *make_internal_rpc_pipe_p(char *pipe_name,
@@ -298,6 +325,10 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
DLIST_ADD(InternalPipes, p);
p->conn = conn;
+
+ /* Ensure the connection isn't idled whilst this pipe is open. */
+ p->conn->num_files_open++;
+
p->vuid = vuid;
p->ntlmssp_chal_flags = 0;
@@ -313,9 +344,10 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
p->pipe_user.uid = (uid_t)-1;
p->pipe_user.gid = (gid_t)-1;
- /* Store the session key */
+ /* Store the session key and NT_TOKEN */
if (vuser) {
memcpy(p->session_key, vuser->session_key, sizeof(p->session_key));
+ p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);
}
/*
@@ -1055,7 +1087,7 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p)
ZERO_STRUCTP(p);
SAFE_FREE(p);
-
+
return True;
}
@@ -1085,6 +1117,8 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn)
DLIST_REMOVE(InternalPipes, p);
+ p->conn->num_files_open--;
+
ZERO_STRUCTP(p);
SAFE_FREE(p);
diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c
index 569f3fb8b1..a096325860 100644
--- a/source3/rpc_server/srv_reg.c
+++ b/source3/rpc_server/srv_reg.c
@@ -1,11 +1,12 @@
-/*
+/*
* 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) Marc Jacobsen 2000.
+ * 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
@@ -26,6 +27,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/*******************************************************************
api_reg_close
********************************************************************/
@@ -53,10 +57,10 @@ static BOOL api_reg_close(pipes_struct *p)
}
/*******************************************************************
- api_reg_open
+ api_reg_open_khlm
********************************************************************/
-static BOOL api_reg_open(pipes_struct *p)
+static BOOL api_reg_open_hklm(pipes_struct *p)
{
REG_Q_OPEN_HKLM q_u;
REG_R_OPEN_HKLM r_u;
@@ -70,7 +74,7 @@ static BOOL api_reg_open(pipes_struct *p)
if(!reg_io_q_open_hklm("", &q_u, data, 0))
return False;
- r_u.status = _reg_open(p, &q_u, &r_u);
+ r_u.status = _reg_open_hklm(p, &q_u, &r_u);
if(!reg_io_r_open_hklm("", &r_u, rdata, 0))
return False;
@@ -79,6 +83,33 @@ static BOOL api_reg_open(pipes_struct *p)
}
/*******************************************************************
+ api_reg_open_khlm
+ ********************************************************************/
+
+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_entry
********************************************************************/
@@ -185,17 +216,98 @@ static BOOL api_reg_abort_shutdown(pipes_struct *p)
/*******************************************************************
+ 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;
+}
+
+
+
+/*******************************************************************
array of \PIPE\reg operations
********************************************************************/
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" , REG_OPEN_HKLM , api_reg_open },
- { "REG_INFO" , REG_INFO , api_reg_info },
- { "REG_SHUTDOWN" , REG_SHUTDOWN , api_reg_shutdown },
- { "REG_ABORT_SHUTDOWN", REG_ABORT_SHUTDOWN, api_reg_abort_shutdown },
- { NULL, 0 , NULL }
+ { "REG_CLOSE" , REG_CLOSE , api_reg_close },
+ { "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry },
+ { "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_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 },
+ { NULL , 0 , NULL }
};
/*******************************************************************
diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c
index adedd4a8fa..3f07e4aaea 100644
--- a/source3/rpc_server/srv_reg_nt.c
+++ b/source3/rpc_server/srv_reg_nt.c
@@ -5,7 +5,8 @@
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
* Copyright (C) Hewlett-Packard Company 1999.
- * Copyright (C) Jeremy Allison 2001.
+ * 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
@@ -26,20 +27,479 @@
#include "includes.h"
-struct reg_info {
- /* for use by \PIPE\winreg */
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+#define KEY_HKLM "HKLM"
+#define KEY_HKU "HKU"
+
+#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())
+
+/* structure to store the registry handles */
+
+typedef struct _RegistryKey {
+ struct _RegistryKey *prev, *next;
+
fstring name; /* name of registry key */
-};
+ POLICY_HND hnd;
+
+} Registry_Key;
+
+static Registry_Key *regkeys_list;
+static TDB_CONTEXT *tdb_reg;
+
+/***********************************************************************
+ Add subkey strings to the registry tdb under a defined key
+ fmt is the same format as tdb_pack except this function only supports
+ fstrings
+ ***********************************************************************/
+
+static BOOL store_reg_keys( TDB_CONTEXT *tdb, char *keyname, char **subkeys, uint32 num_subkeys )
+{
+ TDB_DATA kbuf, dbuf;
+ char *buffer, *tmpbuf;
+ int i = 0;
+ uint32 len, buflen;
+ BOOL ret = True;
+
+ if ( !keyname )
+ return False;
+
+ /* allocate some initial memory */
+
+ buffer = malloc(sizeof(pstring));
+ buflen = sizeof(pstring);
+ len = 0;
+
+ /* store the number of subkeys */
+
+ len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
+
+ /* pack all the strings */
+
+ for (i=0; i<num_subkeys; i++) {
+ len += tdb_pack(buffer+len, buflen-len, "f", subkeys[i]);
+ if ( len > buflen ) {
+ /* allocate some extra space */
+ if ((tmpbuf = Realloc( buffer, len*2 )) == NULL) {
+ DEBUG(0,("store_reg_keys: Failed to realloc memory of size [%d]\n", len*2));
+ ret = False;
+ goto done;
+ }
+ buffer = tmpbuf;
+ buflen = len*2;
+
+ len = tdb_pack(buffer+len, buflen-len, "f", subkeys[i]);
+ }
+ }
+
+ /* finally write out the data */
+
+ kbuf.dptr = keyname;
+ kbuf.dsize = strlen(keyname)+1;
+ dbuf.dptr = buffer;
+ dbuf.dsize = len;
+ if ( tdb_store( tdb, kbuf, dbuf, TDB_REPLACE ) == -1) {
+ ret = False;
+ goto done;
+ }
+
+done:
+ SAFE_FREE( buffer );
+ return ret;
+}
+
+/***********************************************************************
+ Retrieve an array of strings containing subkeys. Memory should be
+ released by the caller. The subkeys are stored in a catenated string
+ of null terminated character strings
+ ***********************************************************************/
+
+static int fetch_reg_keys( TDB_CONTEXT *tdb, char* key, char **subkeys )
+{
+ pstring path;
+ uint32 num_items;
+ TDB_DATA dbuf;
+ char *buf;
+ uint32 buflen, len;
+ int i;
+ char *s;
+
+
+ pstrcpy( path, key );
+
+ /* convert to key format */
+ pstring_sub( path, "\\", "/" );
+
+ dbuf = tdb_fetch_by_string( tdb, path );
+
+ buf = dbuf.dptr;
+ buflen = dbuf.dsize;
+
+ if ( !buf ) {
+ DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key));
+ return 0;
+ }
+
+ len = tdb_unpack( buf, buflen, "d", &num_items);
+ if (num_items) {
+ if ( (*subkeys = (char*)malloc(sizeof(fstring)*num_items)) == NULL ) {
+ DEBUG(0,("fetch_reg_keys: Failed to malloc memory for subkey array containing [%d] items!\n",
+ num_items));
+ num_items = -1;
+ goto done;
+ }
+ }
+
+ s = *subkeys;
+ for (i=0; i<num_items; i++) {
+ len += tdb_unpack( buf+len, buflen-len, "f", s );
+ s += strlen(s) + 1;
+ }
+
+done:
+ SAFE_FREE(dbuf.dptr);
+ return num_items;
+}
+
+/***********************************************************************
+ count the number of subkeys dtored in the registry
+ ***********************************************************************/
+
+static int fetch_reg_keys_count( TDB_CONTEXT *tdb, char* key )
+{
+ pstring path;
+ uint32 num_items;
+ TDB_DATA dbuf;
+ char *buf;
+ uint32 buflen, len;
+
+
+ pstrcpy( path, key );
+
+ /* convert to key format */
+ pstring_sub( path, "\\", "/" );
+
+ dbuf = tdb_fetch_by_string( tdb, path );
+
+ buf = dbuf.dptr;
+ buflen = dbuf.dsize;
+
+ if ( !buf ) {
+ DEBUG(5,("fetch_reg_keys: Failed to fetch any subkeys for [%s]\n", key));
+ return 0;
+ }
+
+ len = tdb_unpack( buf, buflen, "d", &num_items);
+
+ SAFE_FREE( buf );
+
+ return num_items;
+}
+
+/***********************************************************************
+ retreive a specific subkey specified by index. The subkey parameter
+ is assumed to be an fstring.
+ ***********************************************************************/
+
+static BOOL fetch_reg_keys_specific( TDB_CONTEXT *tdb, char* key, char* subkey,
+ uint32 key_index )
+{
+ int num_subkeys, i;
+ char *subkeys = NULL;
+ char *s;
+
+ num_subkeys = fetch_reg_keys( tdb_reg, key, &subkeys );
+ if ( num_subkeys == -1 )
+ return False;
+
+ s = subkeys;
+ for ( i=0; i<num_subkeys; i++ ) {
+ /* copy the key if the index matches */
+ if ( i == key_index ) {
+ fstrcpy( subkey, s );
+ break;
+ }
+
+ /* go onto the next string */
+ s += strlen(s) + 1;
+ }
+
+ SAFE_FREE(subkeys);
+
+ return True;
+}
+
+
+/***********************************************************************
+ Open the registry database
+ ***********************************************************************/
+
+static BOOL init_registry_data( TDB_CONTEXT* registry_tdb )
+{
+ pstring keyname;
+ char *subkeys[3];
+
+ /* HKEY_LOCAL_MACHINE */
+
+ pstrcpy( keyname, KEY_HKLM );
+ subkeys[0] = "SYSTEM";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM" );
+ subkeys[0] = "CurrentControlSet";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet" );
+ subkeys[0] = "Control";
+ subkeys[1] = "services";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 2 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control" );
+ subkeys[0] = "Print";
+ subkeys[1] = "ProduceOptions";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 2 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/Print" );
+ subkeys[0] = "Environments";
+ subkeys[1] = "Forms";
+ subkeys[2] = "Printers";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 3 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control/ProductOptions" );
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/services" );
+ subkeys[0] = "Netlogon";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon" );
+ subkeys[0] = "parameters";
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 1 ))
+ return False;
+
+ pstrcpy( keyname, KEY_HKLM );
+ pstrcat( keyname, "/SYSTEM/CurrentControlSet/services/Netlogon/parameters" );
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ))
+ return False;
+
+
+ /* HKEY_USER */
+
+ pstrcpy( keyname, KEY_HKU );
+ if ( !store_reg_keys( registry_tdb, keyname, subkeys, 0 ) )
+ return False;
+
+ return True;
+}
+
+/***********************************************************************
+ Open the registry database
+ ***********************************************************************/
+
+BOOL init_registry( void )
+{
+ static pid_t local_pid;
+
+
+ if (tdb_reg && local_pid == sys_getpid())
+ return True;
+
+ /*
+ * try to open first without creating so we can determine
+ * if we need to init the data in the registry
+ */
+
+ tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+ if ( !tdb_reg )
+ {
+ tdb_reg = tdb_open_log(lock_path("registry.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ if ( !tdb_reg ) {
+ DEBUG(0,("init_registry: Failed to open registry %s (%s)\n",
+ lock_path("registry.tdb"), strerror(errno) ));
+ return False;
+ }
+
+ DEBUG(10,("init_registry: Successfully created registry tdb\n"));
+
+ /* create the registry here */
+ if ( !init_registry_data( tdb_reg ) ) {
+ DEBUG(0,("init_registry: Failed to initiailize data in registry!\n"));
+ return False;
+ }
+ }
+
+ local_pid = sys_getpid();
+
+ return True;
+}
+
+/******************************************************************
+ 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 **)&regkey)) {
+ DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
+ return NULL;
+ }
+ return regkey;
+}
+
+
+/******************************************************************
+ free() function for Registry_Key
+ *****************************************************************/
+
static void free_reg_info(void *ptr)
{
- struct reg_info *info = (struct reg_info *)ptr;
+ Registry_Key *info = (Registry_Key*)ptr;
+
+ DLIST_REMOVE(regkeys_list, info);
SAFE_FREE(info);
}
/*******************************************************************
- reg_reply_unknown_1
+ Function for open a new registry handle and creating a handle
+ Note that P should be valid & hnd should already have space
+ *******************************************************************/
+
+static BOOL open_registry_key(pipes_struct *p, POLICY_HND *hnd, char *name,
+ uint32 access_granted)
+{
+ Registry_Key *regkey = NULL;
+
+ DEBUG(7,("open_registry_key: name = [%s]\n", name));
+
+ /* All registry keys **must** have a name of non-zero length */
+
+ if (!name || !*name )
+ return False;
+
+ if ((regkey=(Registry_Key*)malloc(sizeof(Registry_Key))) == NULL)
+ return False;
+
+ ZERO_STRUCTP( regkey );
+
+ DLIST_ADD( regkeys_list, regkey );
+
+ /* copy the name and obtain a handle */
+
+ fstrcpy( regkey->name, name );
+
+ DEBUG(7,("open_registry_key: exit\n"));
+
+ return create_policy_hnd( p, hnd, free_reg_info, regkey );
+}
+
+/*******************************************************************
+ 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;
+ char *subkeys = NULL;
+ uint32 len;
+ char *s;
+
+ if ( !key )
+ return False;
+
+ num_subkeys = fetch_reg_keys( tdb_reg, key->name, &subkeys );
+ if ( num_subkeys == -1 )
+ return False;
+
+ /* find the longest string */
+
+ max_len = 0;
+ s = subkeys;
+ for ( i=0; i<num_subkeys; i++ ) {
+ len = strlen(s);
+ max_len = MAX(max_len, len);
+ s += len + 1;
+ }
+
+ *maxnum = num_subkeys;
+ *maxlen = max_len*2;
+
+ SAFE_FREE(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 )
+{
+ if ( !key )
+ return False;
+
+ /* Hard coded key names first */
+ /* nothing has valuies right now */
+
+ *maxnum = 0;
+ *maxlen = 0;
+ *maxsize = 0;
+ return True;
+
+#if 0 /* JERRY */
+ /*
+ * FIXME!!! Need to add routines to look up values in other
+ * databases --jerry
+ */
+
+ return False;
+#endif
+}
+
+/********************************************************************
+ reg_close
********************************************************************/
NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
@@ -48,7 +508,7 @@ NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
ZERO_STRUCT(r_u->pol);
/* close the policy handle */
- if (!close_policy_hnd(p, &q_u->pol))
+ if (!close_registry_key(p, &q_u->pol))
return NT_STATUS_OBJECT_NAME_INVALID;
return NT_STATUS_OK;
@@ -58,9 +518,21 @@ NTSTATUS _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
reg_reply_open
********************************************************************/
-NTSTATUS _reg_open(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
+NTSTATUS _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u)
+{
+ if (!open_registry_key(p, &r_u->pol, KEY_HKLM, 0x0))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ reg_reply_open
+ ********************************************************************/
+
+NTSTATUS _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u)
{
- if (!create_policy_hnd(p, &r_u->pol, free_reg_info, NULL))
+ if (!open_registry_key(p, &r_u->pol, KEY_HKU, 0x0))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
return NT_STATUS_OK;
@@ -74,34 +546,36 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
{
POLICY_HND pol;
fstring name;
- struct reg_info *info = NULL;
+ pstring path;
+ int num_subkeys;
+ Registry_Key *key = find_regkey_index_by_hnd(p, &q_u->pol);
- DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+ DEBUG(5,("reg_open_entry: Enter\n"));
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ 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);
- DEBUG(5,("reg_open_entry: %s\n", name));
-
- /* lkcl XXXX do a check on the name, here */
- if (!strequal(name, "SYSTEM\\CurrentControlSet\\Control\\ProductOptions") &&
- !strequal(name, "System\\CurrentControlSet\\services\\Netlogon\\parameters\\"))
- return NT_STATUS_ACCESS_DENIED;
+ /* store the full path in the regkey_list */
+
+ pstrcpy( path, key->name );
+ pstrcat( path, "\\" );
+ pstrcat( path, name );
- if ((info = (struct reg_info *)malloc(sizeof(struct reg_info))) == NULL)
- return NT_STATUS_NO_MEMORY;
+ DEBUG(5,("reg_open_entry: %s\n", path));
- ZERO_STRUCTP(info);
- fstrcpy(info->name, name);
+ /* do a check on the name, here */
+
+ if ( (num_subkeys=fetch_reg_keys_count( tdb_reg, path )) == -1 )
+ return NT_STATUS_ACCESS_DENIED;
- if (!create_policy_hnd(p, &pol, free_reg_info, (void *)info))
- return NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
+ if (!open_registry_key(p, &pol, path, 0x0))
+ return NT_STATUS_TOO_MANY_SECRETS;
init_reg_r_open_entry(r_u, &pol, NT_STATUS_OK);
- DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+ DEBUG(5,("reg_open_entry: Exitn"));
return r_u->status;
}
@@ -113,21 +587,23 @@ NTSTATUS _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTR
NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
{
NTSTATUS status = NT_STATUS_OK;
- char *key = NULL;
- uint32 type=0x1; /* key type: REG_SZ */
-
+ char *value = NULL;
+ uint32 type = 0x1; /* key type: REG_SZ */
UNISTR2 *uni_key = NULL;
BUFFER2 *buf = NULL;
fstring name;
+ Registry_Key *key = find_regkey_index_by_hnd( p, &q_u->pol );
- DEBUG(5,("_reg_info: %d\n", __LINE__));
+ DEBUG(5,("_reg_info: Enter\n"));
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if ( !key )
return NT_STATUS_INVALID_HANDLE;
+
+ DEBUG(7,("_reg_info: policy key name = [%s]\n", key->name));
rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0);
- DEBUG(5,("reg_info: checking key: %s\n", name));
+ DEBUG(5,("reg_info: checking subkey: %s\n", name));
uni_key = (UNISTR2 *)talloc_zero(p->mem_ctx, sizeof(UNISTR2));
buf = (BUFFER2 *)talloc_zero(p->mem_ctx, sizeof(BUFFER2));
@@ -147,33 +623,126 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
}
switch (lp_server_role()) {
- case ROLE_DOMAIN_PDC:
- case ROLE_DOMAIN_BDC:
- key = "LanmanNT";
- break;
- case ROLE_STANDALONE:
- key = "ServerNT";
- break;
- case ROLE_DOMAIN_MEMBER:
- key = "WinNT";
- break;
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ value = "LanmanNT";
+ break;
+ case ROLE_STANDALONE:
+ value = "ServerNT";
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ value = "WinNT";
+ break;
}
/* 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. */
- init_unistr2(uni_key, key, strlen(key)+1);
+ init_unistr2(uni_key, value, strlen(value)+1);
init_buffer2(buf, (uint8*)uni_key->buffer, uni_key->uni_str_len*2);
out:
init_reg_r_info(q_u->ptr_buf, r_u, buf, type, status);
- DEBUG(5,("reg_open_entry: %d\n", __LINE__));
+ DEBUG(5,("reg_open_entry: 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 );
+ fstring subkey;
+
+
+ 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( tdb_reg, regkey->name, subkey, q_u->key_index ) )
+ {
+ status = werror_to_ntstatus( WERR_NO_MORE_ITEMS );
+ 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:
return status;
}
+
/*******************************************************************
reg_shutdwon
********************************************************************/
@@ -219,6 +788,10 @@ NTSTATUS _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u
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;
@@ -234,3 +807,5 @@ NTSTATUS _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_A
return status;
}
+
+
diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c
index c555305bce..f002a7d1c9 100644
--- a/source3/rpc_server/srv_samr.c
+++ b/source3/rpc_server/srv_samr.c
@@ -32,6 +32,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/*******************************************************************
api_samr_close_hnd
********************************************************************/
@@ -124,6 +127,37 @@ static BOOL api_samr_get_usrdom_pwinfo(pipes_struct *p)
}
/*******************************************************************
+ api_samr_set_sec_obj
+ ********************************************************************/
+
+static BOOL api_samr_set_sec_obj(pipes_struct *p)
+{
+ SAMR_Q_SET_SEC_OBJ q_u;
+ SAMR_R_SET_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(!samr_io_q_set_sec_obj("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_set_sec_obj: unable to unmarshall SAMR_Q_SET_SEC_OBJ.\n"));
+ return False;
+ }
+
+ r_u.status = _samr_set_sec_obj(p, &q_u, &r_u);
+
+ if(!samr_io_r_set_sec_obj("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_set_sec_obj: unable to marshall SAMR_R_SET_SEC_OBJ.\n"));
+ return False;
+ }
+
+
+ return True;
+}
+
+/*******************************************************************
api_samr_query_sec_obj
********************************************************************/
@@ -1427,6 +1461,7 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
{"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj },
+ {"SAMR_SET_SEC_OBJECT" , SAMR_SET_SEC_OBJECT , api_samr_set_sec_obj },
{"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo},
{"SAMR_UNKNOWN_2E" , SAMR_UNKNOWN_2E , api_samr_unknown_2e },
{"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info },
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 106d7c1923..88d728d810 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -29,9 +29,11 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern fstring global_myworkgroup;
extern pstring global_myname;
-extern DOM_SID global_sam_sid;
extern DOM_SID global_sid_Builtin;
extern rid_name domain_group_rids[];
@@ -52,9 +54,69 @@ struct samr_info {
/* for use by the \PIPE\samr policy */
DOM_SID sid;
uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */
+ uint32 acc_granted;
DISP_INFO disp_info;
+
+ TALLOC_CTX *mem_ctx;
};
+struct generic_mapping sam_generic_mapping = {SAMR_READ, SAMR_WRITE, SAMR_EXECUTE, SAMR_ALL_ACCESS};
+struct generic_mapping dom_generic_mapping = {DOMAIN_READ, DOMAIN_WRITE, DOMAIN_EXECUTE, DOMAIN_ALL_ACCESS};
+struct generic_mapping usr_generic_mapping = {USER_READ, USER_WRITE, USER_EXECUTE, USER_ALL_ACCESS};
+struct generic_mapping grp_generic_mapping = {GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, GROUP_ALL_ACCESS};
+struct generic_mapping ali_generic_mapping = {ALIAS_READ, ALIAS_WRITE, ALIAS_EXECUTE, ALIAS_ALL_ACCESS};
+
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *d_size);
+
+
+/*******************************************************************
+ Checks if access to an object should be granted, and returns that
+ level of access for further checks.
+********************************************************************/
+
+NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_token, uint32 des_access,
+ uint32 *acc_granted, const char *debug)
+{
+ NTSTATUS status = NT_STATUS_ACCESS_DENIED;
+
+ if (!se_access_check(psd, nt_user_token, des_access, acc_granted, &status)) {
+ if (geteuid() == sec_initial_uid()) {
+ DEBUG(4,("%s: ACCESS should be DENIED (requested: %#010x)\n",
+ debug, des_access));
+ DEBUGADD(4,("but overritten by euid == sec_initial_uid()\n"));
+ status = NT_STATUS_OK;
+ }
+ else {
+ DEBUG(2,("%s: ACCESS DENIED (requested: %#010x)\n",
+ debug, des_access));
+ }
+ }
+ return status;
+}
+
+/*******************************************************************
+ Checks if access to a function can be granted
+********************************************************************/
+
+NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_required, const char *debug)
+{
+ DEBUG(5,("%s: access check ((granted: %#010x; required: %#010x)\n",
+ debug, acc_granted, acc_required));
+ if ((acc_granted & acc_required) != acc_required) {
+ if (geteuid() == sec_initial_uid()) {
+ DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+ debug, acc_granted, acc_required));
+ DEBUGADD(4,("but overwritten by euid == 0\n"));
+ return NT_STATUS_OK;
+ }
+ DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n",
+ debug, acc_granted, acc_required));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
+
/*******************************************************************
Create a samr_info struct.
********************************************************************/
@@ -63,17 +125,27 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
{
struct samr_info *info;
fstring sid_str;
+ TALLOC_CTX *mem_ctx;
+
+ if (psid) {
+ sid_to_string(sid_str, psid);
+ } else {
+ fstrcpy(sid_str,"(NULL)");
+ }
+
+ mem_ctx = talloc_init_named("samr_info for domain sid %s", sid_str);
- if ((info = (struct samr_info *)malloc(sizeof(struct samr_info))) == NULL)
+ if ((info = (struct samr_info *)talloc(mem_ctx, sizeof(struct samr_info))) == NULL)
return NULL;
ZERO_STRUCTP(info);
+ DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_str));
if (psid) {
- DEBUG(10,("get_samr_info_by_sid: created new info for sid %s\n", sid_to_string(sid_str, psid) ));
sid_copy( &info->sid, psid);
} else {
DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));
}
+ info->mem_ctx = mem_ctx;
return info;
}
@@ -84,18 +156,13 @@ static void free_samr_db(struct samr_info *info)
{
int i;
- if (info->disp_info.group_dbloaded) {
- for (i=0; i<info->disp_info.num_group_account; i++)
- SAFE_FREE(info->disp_info.disp_group_info[i].grp);
-
- SAFE_FREE(info->disp_info.disp_group_info);
- }
+ /* Groups are talloced */
if (info->disp_info.user_dbloaded){
- for (i=0; i<info->disp_info.num_user_account; i++)
+ for (i=0; i<info->disp_info.num_user_account; i++) {
+ /* Not really a free, actually a 'clear' */
pdb_free_sam(&info->disp_info.disp_user_info[i].sam);
-
- SAFE_FREE(info->disp_info.disp_user_info);
+ }
}
info->disp_info.user_dbloaded=False;
@@ -110,26 +177,13 @@ static void free_samr_info(void *ptr)
struct samr_info *info=(struct samr_info *) ptr;
free_samr_db(info);
- SAFE_FREE(info);
+ talloc_destroy(info->mem_ctx);
}
/*******************************************************************
Ensure password info is never given out. Paranioa... JRA.
********************************************************************/
-static void samr_clear_passwd_fields( SAM_USER_INFO_21 *pass, int num_entries)
-{
- int i;
-
- if (!pass)
- return;
-
- for (i = 0; i < num_entries; i++) {
- memset(&pass[i].lm_pwd, '\0', sizeof(pass[i].lm_pwd));
- memset(&pass[i].nt_pwd, '\0', sizeof(pass[i].nt_pwd));
- }
-}
-
static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
{
@@ -147,6 +201,8 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
{
SAM_ACCOUNT *pwd = NULL;
DISP_USER_INFO *pwd_array = NULL;
+ NTSTATUS nt_status = NT_STATUS_OK;
+ TALLOC_CTX *mem_ctx = info->mem_ctx;
DEBUG(10,("load_sampwd_entries\n"));
@@ -161,7 +217,8 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
return NT_STATUS_ACCESS_DENIED;
}
- for (pdb_init_sam(&pwd); pdb_getsampwent(pwd) == True; pwd=NULL, pdb_init_sam(&pwd) ) {
+ for (; (NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, &pwd)))
+ && pdb_getsampwent(pwd) == True; pwd=NULL) {
if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) {
pdb_free_sam(&pwd);
@@ -173,7 +230,7 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
if (info->disp_info.num_user_account % MAX_SAM_ENTRIES == 0) {
DEBUG(10,("load_sampwd_entries: allocating more memory\n"));
- pwd_array=(DISP_USER_INFO *)Realloc(info->disp_info.disp_user_info,
+ pwd_array=(DISP_USER_INFO *)talloc_realloc(mem_ctx, info->disp_info.disp_user_info,
(info->disp_info.num_user_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO));
if (pwd_array==NULL)
@@ -198,7 +255,7 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
DEBUG(12,("load_sampwd_entries: done\n"));
- return NT_STATUS_OK;
+ return nt_status;
}
static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
@@ -207,6 +264,7 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
DISP_GROUP_INFO *grp_array = NULL;
uint32 group_entries = 0;
uint32 i;
+ TALLOC_CTX *mem_ctx = info->mem_ctx;
DEBUG(10,("load_group_domain_entries\n"));
@@ -216,11 +274,13 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
return NT_STATUS_OK;
}
- enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV);
+ if (!enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) {
+ return NT_STATUS_NO_MEMORY;
+ }
info->disp_info.num_group_account=group_entries;
- grp_array=(DISP_GROUP_INFO *)malloc(info->disp_info.num_group_account*sizeof(DISP_GROUP_INFO));
+ grp_array=(DISP_GROUP_INFO *)talloc(mem_ctx, info->disp_info.num_group_account*sizeof(DISP_GROUP_INFO));
if (group_entries!=0 && grp_array==NULL) {
SAFE_FREE(map);
@@ -231,7 +291,7 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
for (i=0; i<group_entries; i++) {
- grp_array[i].grp=(DOMAIN_GRP *)malloc(sizeof(DOMAIN_GRP));
+ grp_array[i].grp=(DOMAIN_GRP *)talloc(mem_ctx, sizeof(DOMAIN_GRP));
fstrcpy(grp_array[i].grp->name, map[i].nt_name);
fstrcpy(grp_array[i].grp->comment, map[i].comment);
@@ -252,84 +312,6 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid)
/*******************************************************************
- This next function should be replaced with something that
- dynamically returns the correct user info..... JRA.
- ********************************************************************/
-
-static NTSTATUS get_sampwd_entries(SAM_USER_INFO_21 *pw_buf, int start_idx,
- int *total_entries, int *num_entries,
- int max_num_entries, uint16 acb_mask)
-{
- SAM_ACCOUNT *pwd = NULL;
- BOOL not_finished = True;
-
- (*num_entries) = 0;
- (*total_entries) = 0;
-
- if (pw_buf == NULL)
- return NT_STATUS_NO_MEMORY;
-
- pdb_init_sam(&pwd);
-
- if (!pdb_setsampwent(False)) {
- DEBUG(0, ("get_sampwd_entries: Unable to open passdb.\n"));
- pdb_free_sam(&pwd);
- return NT_STATUS_ACCESS_DENIED;
- }
-
- while (((not_finished = pdb_getsampwent(pwd)) != False)
- && (*num_entries) < max_num_entries)
- {
- int user_name_len;
-
- if (start_idx > 0) {
-
- pdb_reset_sam(pwd);
-
- /* skip the requested number of entries.
- not very efficient, but hey... */
- start_idx--;
- continue;
- }
-
- user_name_len = strlen(pdb_get_username(pwd))+1;
- init_unistr2(&pw_buf[(*num_entries)].uni_user_name, pdb_get_username(pwd), user_name_len);
- init_uni_hdr(&pw_buf[(*num_entries)].hdr_user_name, user_name_len);
- pw_buf[(*num_entries)].user_rid = pdb_get_user_rid(pwd);
- memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
-
- /* Now check if the NT compatible password is available. */
- if (pdb_get_nt_passwd(pwd))
- memcpy( pw_buf[(*num_entries)].nt_pwd , pdb_get_nt_passwd(pwd), 16);
-
- pw_buf[(*num_entries)].acb_info = pdb_get_acct_ctrl(pwd);
-
- DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
- (*num_entries), pdb_get_username(pwd), pdb_get_user_rid(pwd), pdb_get_acct_ctrl(pwd) ));
-
- if (acb_mask == 0 || (pdb_get_acct_ctrl(pwd) & acb_mask)) {
- DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
- (*num_entries)++;
- } else {
- DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
- }
-
- (*total_entries)++;
-
- pdb_reset_sam(pwd);
-
- }
-
- pdb_endsampwent();
- pdb_free_sam(&pwd);
-
- if (not_finished)
- return STATUS_MORE_ENTRIES;
- else
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
_samr_close_hnd
********************************************************************/
@@ -352,17 +334,37 @@ NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HN
NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u)
{
- struct samr_info *info;
+ struct samr_info *info;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->flags;
+ size_t sd_size;
+ NTSTATUS status;
r_u->status = NT_STATUS_OK;
/* find the connection policy handle. */
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
return NT_STATUS_INVALID_HANDLE;
+ if (!NT_STATUS_IS_OK(status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN,"_samr_open_domain"))) {
+ return status;
+ }
+
+ /*check if access can be granted as requested by client. */
+ samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+ se_map_generic(&des_access,&dom_generic_mapping);
+
+ if (!NT_STATUS_IS_OK(status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_open_domain"))) {
+ return status;
+ }
+
/* associate the domain SID with the (unique) handle. */
if ((info = get_samr_info_by_sid(&q_u->dom_sid.sid))==NULL)
return NT_STATUS_NO_MEMORY;
+ info->acc_granted = acc_granted;
/* get a (unique) handle. open a policy on it. */
if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info))
@@ -402,11 +404,90 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
return r_u->status;
}
+
+/*******************************************************************
+ samr_make_sam_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, SAMR_EXECUTE | SAMR_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, SAMR_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ samr_make_dom_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, DOMAIN_EXECUTE | DOMAIN_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, DOMAIN_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
/*******************************************************************
samr_make_usr_obj_sd
********************************************************************/
-static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SID *usr_sid)
+static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size, DOM_SID *usr_sid)
{
extern DOM_SID global_sid_World;
DOM_SID adm_sid;
@@ -416,8 +497,6 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI
SEC_ACCESS mask;
SEC_ACL *psa = NULL;
- SEC_DESC *psd = NULL;
- size_t sd_size;
sid_copy(&adm_sid, &global_sid_Builtin);
sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
@@ -425,29 +504,107 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC_BUF **buf, DOM_SI
sid_copy(&act_sid, &global_sid_Builtin);
sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
- init_sec_access(&mask, 0x2035b);
+ /*basic access for every one*/
+ init_sec_access(&mask, USER_EXECUTE | USER_READ);
init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_access(&mask, 0xf07ff);
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, USER_ALL_ACCESS);
init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_access(&mask,0x20044);
+ /*extended access for the user*/
+ init_sec_access(&mask,READ_CONTROL_ACCESS | USER_ACCESS_CHANGE_PASSWORD | USER_ACCESS_SET_LOC_COM);
init_sec_ace(&ace[3], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- if((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
return NT_STATUS_NO_MEMORY;
- if((psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, &sd_size)) == NULL)
+ return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ samr_make_grp_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, GROUP_EXECUTE | GROUP_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, GROUP_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
return NT_STATUS_NO_MEMORY;
- if((*buf = make_sec_desc_buf(ctx, sd_size, psd)) == NULL)
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
return NT_STATUS_NO_MEMORY;
return NT_STATUS_OK;
}
-static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid)
+/*******************************************************************
+ samr_make_ali_obj_sd
+ ********************************************************************/
+
+static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+ extern DOM_SID global_sid_World;
+ DOM_SID adm_sid;
+ DOM_SID act_sid;
+
+ SEC_ACE ace[3];
+ SEC_ACCESS mask;
+
+ SEC_ACL *psa = NULL;
+
+ sid_copy(&adm_sid, &global_sid_Builtin);
+ sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+ sid_copy(&act_sid, &global_sid_Builtin);
+ sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+ /*basic access for every one*/
+ init_sec_access(&mask, ALIAS_EXECUTE | ALIAS_READ);
+ init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, ALIAS_ALL_ACCESS);
+ init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ return NT_STATUS_OK;
+}
+
+static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted)
{
struct samr_info *info = NULL;
@@ -459,10 +616,22 @@ static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *s
return False;
*sid = info->sid;
+ *acc_granted = info->acc_granted;
return True;
}
/*******************************************************************
+ _samr_set_sec_obj
+ ********************************************************************/
+
+NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_SEC_OBJ *r_u)
+{
+ DEBUG(0,("_samr_set_sec_obj: Not yet implemented!\n"));
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+
+/*******************************************************************
_samr_query_sec_obj
********************************************************************/
@@ -470,17 +639,52 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
{
DOM_SID pol_sid;
fstring str_sid;
+ SEC_DESC * psd = NULL;
+ size_t sd_size;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
/* Get the SID. */
-
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+
DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", sid_to_string(str_sid, &pol_sid)));
- r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &r_u->buf, &pol_sid);
+ /* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */
+
+ /* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */
+ if (pol_sid.sid_rev_num == 0)
+ {
+ DEBUG(5,("_samr_query_sec_obj: querying security on SAM\n"));
+ r_u->status = samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ }
+ else if (sid_equal(&pol_sid,get_global_sam_sid())) /* check if it is our domain SID */
+
+ {
+ DEBUG(5,("_samr_query_sec_obj: querying security on Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+ r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+ }
+ else if (sid_equal(&pol_sid,&global_sid_Builtin)) /* check if it is the Builtin Domain */
+ {
+ /* TODO: Builtin probably needs a different SD with restricted write access*/
+ DEBUG(5,("_samr_query_sec_obj: querying security on Builtin Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+ r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+ }
+ else if (sid_check_is_in_our_domain(&pol_sid) ||
+ sid_check_is_in_builtin(&pol_sid))
+ {
+ /* TODO: different SDs have to be generated for aliases groups and users.
+ Currently all three get a default user SD */
+ DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
+ r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &psd,&sd_size, &pol_sid);
+ }
+ else return NT_STATUS_OBJECT_TYPE_MISMATCH;
+
+ if ((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
+ return NT_STATUS_NO_MEMORY;
if (NT_STATUS_IS_OK(r_u->status))
r_u->ptr = 1;
@@ -492,69 +696,123 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
makes a SAM_ENTRY / UNISTR2* structure from a user list.
********************************************************************/
-static void make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
- uint32 num_sam_entries, SAM_USER_INFO_21 *pass)
+static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp,
+ uint32 num_entries, uint32 start_idx, DISP_USER_INFO *disp_user_info,
+ DOM_SID *domain_sid)
{
uint32 i;
SAM_ENTRY *sam;
UNISTR2 *uni_name;
-
+ SAM_ACCOUNT *pwd = NULL;
+ UNISTR2 uni_temp_name;
+ const char *temp_name;
+ const DOM_SID *user_sid;
+ uint32 user_rid;
+ fstring user_sid_string;
+ fstring domain_sid_string;
+
*sam_pp = NULL;
*uni_name_pp = NULL;
- if (num_sam_entries == 0)
- return;
+ if (num_entries == 0)
+ return NT_STATUS_OK;
- sam = (SAM_ENTRY *)talloc_zero(ctx, sizeof(SAM_ENTRY)*num_sam_entries);
+ sam = (SAM_ENTRY *)talloc_zero(ctx, sizeof(SAM_ENTRY)*num_entries);
- uni_name = (UNISTR2 *)talloc_zero(ctx, sizeof(UNISTR2)*num_sam_entries);
+ uni_name = (UNISTR2 *)talloc_zero(ctx, sizeof(UNISTR2)*num_entries);
if (sam == NULL || uni_name == NULL) {
- DEBUG(0, ("NULL pointers in SAMR_R_QUERY_DISPINFO\n"));
- return;
+ DEBUG(0, ("make_user_sam_entry_list: talloc_zero failed!\n"));
+ return NT_STATUS_NO_MEMORY;
}
- ZERO_STRUCTP(sam);
- ZERO_STRUCTP(uni_name);
-
- for (i = 0; i < num_sam_entries; i++) {
- int len = pass[i].uni_user_name.uni_str_len;
+ for (i = 0; i < num_entries; i++) {
+ int len = uni_temp_name.uni_str_len;
+
+ pwd = disp_user_info[i+start_idx].sam;
+ temp_name = pdb_get_username(pwd);
+ init_unistr2(&uni_temp_name, temp_name, strlen(temp_name)+1);
+ user_sid = pdb_get_user_sid(pwd);
+
+ if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
+ DEBUG(0, ("make_user_sam_entry_list: User %s has SID %s, which conflicts with "
+ "the domain sid %s. Failing operation.\n",
+ temp_name,
+ sid_to_string(user_sid_string, user_sid),
+ sid_to_string(domain_sid_string, domain_sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
- init_sam_entry(&sam[i], len, pass[i].user_rid);
- copy_unistr2(&uni_name[i], &pass[i].uni_user_name);
+ init_sam_entry(&sam[i], len, user_rid);
+ copy_unistr2(&uni_name[i], &uni_temp_name);
}
*sam_pp = sam;
*uni_name_pp = uni_name;
+ return NT_STATUS_OK;
}
/*******************************************************************
samr_reply_enum_dom_users
********************************************************************/
-NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, SAMR_R_ENUM_DOM_USERS *r_u)
+NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
+ SAMR_R_ENUM_DOM_USERS *r_u)
{
- SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
- int num_entries = 0;
- int total_entries = 0;
+ struct samr_info *info = NULL;
+ uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
+ int num_account;
+ uint32 enum_context=q_u->start_idx;
+ uint32 max_size=q_u->max_size;
+ uint32 temp_size;
+ enum remote_arch_types ra_type = get_remote_arch();
+ int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
+ uint32 max_entries = max_sam_entries;
+ DOM_SID domain_sid;
r_u->status = NT_STATUS_OK;
/* find the policy handle. open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
+ domain_sid = info->sid;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted,
+ DOMAIN_ACCESS_ENUM_ACCOUNTS,
+ "_samr_enum_dom_users"))) {
+ return r_u->status;
+ }
+
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
become_root();
- r_u->status = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries,
- MAX_SAM_ENTRIES, q_u->acb_mask);
+ r_u->status=load_sampwd_entries(info, q_u->acb_mask);
unbecome_root();
-
- if (NT_STATUS_IS_ERR(r_u->status))
+
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- samr_clear_passwd_fields(pass, num_entries);
+ num_account = info->disp_info.num_user_account;
+
+ if (enum_context > num_account) {
+ DEBUG(5, ("_samr_enum_dom_users: enumeration handle over total entries\n"));
+ return NT_STATUS_OK;
+ }
+
+ /* verify we won't overflow */
+ if (max_entries > num_account-enum_context) {
+ max_entries = num_account-enum_context;
+ DEBUG(5, ("_samr_enum_dom_users: only %d entries to return\n", max_entries));
+ }
+
+ /* calculate the size and limit on the number of entries we will return */
+ temp_size=max_entries*struct_size;
+
+ if (temp_size>max_size) {
+ max_entries=MIN((max_size/struct_size),max_entries);;
+ DEBUG(5, ("_samr_enum_dom_users: buffer size limits to only %d entries\n", max_entries));
+ }
/*
* Note from JRA. total_entries is not being used here. Currently if there is a
@@ -569,9 +827,20 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u, SAMR_
* value (again I think this is wrong).
*/
- make_user_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_acct_name, num_entries, pass);
+ r_u->status = make_user_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_acct_name,
+ max_entries, enum_context,
+ info->disp_info.disp_user_info,
+ &domain_sid);
- init_samr_r_enum_dom_users(r_u, q_u->start_idx + num_entries, num_entries);
+ if (!NT_STATUS_IS_OK(r_u->status))
+ return r_u->status;
+
+ if (enum_context+max_entries < num_account)
+ r_u->status = STATUS_MORE_ENTRIES;
+
+ DEBUG(5, ("_samr_enum_dom_users: %d\n", __LINE__));
+
+ init_samr_r_enum_dom_users(r_u, q_u->start_idx + max_entries, max_entries);
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
@@ -654,13 +923,12 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM
}
SAFE_FREE(map);
- } else if (sid_equal(sid, &global_sam_sid) && !lp_hide_local_users()) {
+ } else if (sid_equal(sid, get_global_sam_sid()) && !lp_hide_local_users()) {
struct sys_grent *glist;
struct sys_grent *grp;
struct passwd *pw;
gid_t winbind_gid_low, winbind_gid_high;
-
- lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
+ BOOL winbind_groups_exist = lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
/* local aliases */
/* we return the UNIX groups here. This seems to be the right */
@@ -690,24 +958,15 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM
continue;
/* Don't return winbind groups as they are not local! */
- if ((grp->gr_gid >= winbind_gid_low)&&(grp->gr_gid <= winbind_gid_high)) {
+ if (winbind_groups_exist && (grp->gr_gid >= winbind_gid_low)&&(grp->gr_gid <= winbind_gid_high)) {
DEBUG(10,("get_group_alias_entries: not returing %s, not local.\n", smap.nt_name ));
continue;
}
/* Don't return user private groups... */
-
- /*
- * We used to do a Get_Pwnam() here, but this has been
- * trimmed back to the common case for private groups
- * to save lookups and to use the _alloc interface.
- *
- * This also matches the group mapping code
- */
- if ((pw = getpwnam_alloc(smap.nt_name)) != 0) {
+ if ((pw = Get_Pwnam(smap.nt_name)) != 0) {
DEBUG(10,("get_group_alias_entries: not returing %s, clashes with user.\n", smap.nt_name ));
- passwd_free(&pw);
continue;
}
@@ -808,11 +1067,16 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM
DOMAIN_GRP *grp=NULL;
uint32 num_entries;
DOM_SID sid;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_groups"))) {
+ return r_u->status;
+ }
DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
@@ -840,12 +1104,17 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S
fstring sid_str;
DOM_SID sid;
NTSTATUS status;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_ENUM_ACCOUNTS, "_samr_enum_dom_aliases"))) {
+ return r_u->status;
+ }
+
sid_to_string(sid_str, &sid);
DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
@@ -867,7 +1136,8 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S
/*******************************************************************
samr_reply_query_dispinfo
********************************************************************/
-NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_QUERY_DISPINFO *r_u)
+NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
+ SAMR_R_QUERY_DISPINFO *r_u)
{
struct samr_info *info = NULL;
uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
@@ -882,9 +1152,8 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
NTSTATUS disp_ret;
uint32 num_account = 0;
enum remote_arch_types ra_type = get_remote_arch();
- int max_sam_entries;
-
- max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
+ int max_sam_entries = (ra_type == RA_WIN95) ? MAX_SAM_ENTRIES_W95 : MAX_SAM_ENTRIES_W2K;
+ DOM_SID domain_sid;
DEBUG(5, ("samr_reply_query_dispinfo: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
@@ -893,6 +1162,8 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
+ domain_sid = info->sid;
+
/*
* calculate how many entries we will return.
* based on
@@ -936,7 +1207,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
become_root();
r_u->status=load_sampwd_entries(info, acb_mask);
unbecome_root();
- if (NT_STATUS_IS_ERR(r_u->status)) {
+ if (!NT_STATUS_IS_OK(r_u->status)) {
DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
return r_u->status;
}
@@ -945,7 +1216,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
case 0x3:
case 0x5:
r_u->status = load_group_domain_entries(info, &info->sid);
- if (NT_STATUS_IS_ERR(r_u->status))
+ if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
num_account = info->disp_info.num_group_account;
break;
@@ -962,7 +1233,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
if (enum_context > num_account) {
DEBUG(5, ("samr_reply_query_dispinfo: enumeration handle over total entries\n"));
- return NT_STATUS_OK;
+ return NT_STATUS_NO_MORE_ENTRIES;
}
/* verify we won't overflow */
@@ -991,8 +1262,9 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
if (!(ctr->sam.info1 = (SAM_DISPINFO_1 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_1))))
return NT_STATUS_NO_MEMORY;
}
- disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context, info->disp_info.disp_user_info);
- if (NT_STATUS_IS_ERR(disp_ret))
+ disp_ret = init_sam_dispinfo_1(p->mem_ctx, ctr->sam.info1, max_entries, enum_context,
+ info->disp_info.disp_user_info, &domain_sid);
+ if (!NT_STATUS_IS_OK(disp_ret))
return disp_ret;
break;
case 0x2:
@@ -1000,8 +1272,9 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
if (!(ctr->sam.info2 = (SAM_DISPINFO_2 *)talloc_zero(p->mem_ctx,max_entries*sizeof(SAM_DISPINFO_2))))
return NT_STATUS_NO_MEMORY;
}
- disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context, info->disp_info.disp_user_info);
- if (NT_STATUS_IS_ERR(disp_ret))
+ disp_ret = init_sam_dispinfo_2(p->mem_ctx, ctr->sam.info2, max_entries, enum_context,
+ info->disp_info.disp_user_info, &domain_sid);
+ if (!NT_STATUS_IS_OK(disp_ret))
return disp_ret;
break;
case 0x3:
@@ -1010,7 +1283,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
return NT_STATUS_NO_MEMORY;
}
disp_ret = init_sam_dispinfo_3(p->mem_ctx, ctr->sam.info3, max_entries, enum_context, info->disp_info.disp_group_info);
- if (NT_STATUS_IS_ERR(disp_ret))
+ if (!NT_STATUS_IS_OK(disp_ret))
return disp_ret;
break;
case 0x4:
@@ -1019,7 +1292,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
return NT_STATUS_NO_MEMORY;
}
disp_ret = init_sam_dispinfo_4(p->mem_ctx, ctr->sam.info4, max_entries, enum_context, info->disp_info.disp_user_info);
- if (NT_STATUS_IS_ERR(disp_ret))
+ if (!NT_STATUS_IS_OK(disp_ret))
return disp_ret;
break;
case 0x5:
@@ -1028,7 +1301,7 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
return NT_STATUS_NO_MEMORY;
}
disp_ret = init_sam_dispinfo_5(p->mem_ctx, ctr->sam.info5, max_entries, enum_context, info->disp_info.disp_group_info);
- if (NT_STATUS_IS_ERR(disp_ret))
+ if (!NT_STATUS_IS_OK(disp_ret))
return disp_ret;
break;
@@ -1057,22 +1330,26 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_
NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAMR_R_QUERY_ALIASINFO *r_u)
{
- struct samr_info *info = NULL;
+ DOM_SID sid;
GROUP_MAP map;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_LOOKUP_INFO, "_samr_query_aliasinfo"))) {
+ return r_u->status;
+ }
- if (!sid_check_is_in_our_domain(&info->sid) &&
- !sid_check_is_in_builtin(&info->sid))
+ if (!sid_check_is_in_our_domain(&sid) &&
+ !sid_check_is_in_builtin(&sid))
return NT_STATUS_OBJECT_TYPE_MISMATCH;
- if(!get_local_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
+ if (!get_local_group_from_sid(sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_ALIAS;
switch (q_u->switch_level) {
@@ -1169,6 +1446,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
int num_rids = q_u->num_names2;
DOM_SID pol_sid;
fstring sid_str;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
@@ -1177,10 +1455,14 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
ZERO_ARRAY(rid);
ZERO_ARRAY(type);
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid)) {
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted)) {
init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH);
return r_u->status;
}
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, 0, "_samr_lookup_names"))) { /* Don't know the acc_bits yet */
+ return r_u->status;
+ }
if (num_rids > MAX_SAM_ENTRIES) {
num_rids = MAX_SAM_ENTRIES;
@@ -1324,13 +1606,14 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
DOM_SID pol_sid;
int num_rids = q_u->num_rids1;
int i;
+ uint32 acc_granted;
r_u->status = NT_STATUS_OK;
DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
if (num_rids > MAX_SAM_ENTRIES) {
@@ -1356,7 +1639,7 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
group_attrs[i] = SID_NAME_UNKNOWN;
*group_names[i] = '\0';
- if (sid_equal(&pol_sid, &global_sam_sid)) {
+ if (sid_equal(&pol_sid, get_global_sam_sid())) {
sid_copy(&sid, &pol_sid);
sid_append_rid(&sid, q_u->rid[i]);
@@ -1390,42 +1673,58 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN
SAM_ACCOUNT *sampass=NULL;
DOM_SID sid;
POLICY_HND domain_pol = q_u->domain_pol;
- uint32 user_rid = q_u->user_rid;
POLICY_HND *user_pol = &r_u->user_pol;
struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->access_mask;
+ size_t sd_size;
BOOL ret;
+ NTSTATUS nt_status;
r_u->status = NT_STATUS_OK;
- /* find the domain policy handle. */
- if (!find_policy_by_hnd(p, &domain_pol, NULL))
+ /* find the domain policy handle and get domain SID / access bits in the domain policy. */
+ if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_user"))) {
+ return nt_status;
+ }
- pdb_init_sam(&sampass);
+ nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ /* append the user's RID to it */
+ if (!sid_append_rid(&sid, q_u->user_rid))
+ return NT_STATUS_NO_SUCH_USER;
+
+ /* check if access can be granted as requested by client. */
+ samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid);
+ se_map_generic(&des_access, &usr_generic_mapping);
+ if (!NT_STATUS_IS_OK(nt_status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_open_user"))) {
+ return nt_status;
+ }
become_root();
- ret=pdb_getsampwrid(sampass, user_rid);
+ ret=pdb_getsampwsid(sampass, &sid);
unbecome_root();
- /* check that the RID exists in our domain. */
+ /* check that the SID exists in our domain. */
if (ret == False) {
- pdb_free_sam(&sampass);
return NT_STATUS_NO_SUCH_USER;
}
pdb_free_sam(&sampass);
- /* Get the domain SID stored in the domain policy */
- if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
- return NT_STATUS_INVALID_HANDLE;
-
- /* append the user's RID to it */
- if(!sid_append_rid(&sid, user_rid))
- return NT_STATUS_NO_SUCH_USER;
-
- /* associate the user's SID with the new handle. */
+ /* associate the user's SID and access bits with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL)
return NT_STATUS_NO_MEMORY;
+ info->acc_granted = acc_granted;
/* get a (unique) handle. open a policy on it. */
if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info))
@@ -1438,21 +1737,25 @@ NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN
get_user_info_10. Safe. Only gives out acb bits.
*************************************************************************/
-static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
+static NTSTATUS get_user_info_10(TALLOC_CTX *mem_ctx, SAM_USER_INFO_10 *id10, DOM_SID *user_sid)
{
SAM_ACCOUNT *smbpass=NULL;
BOOL ret;
+ NTSTATUS nt_status;
- pdb_init_sam(&smbpass);
+ nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
become_root();
- ret = pdb_getsampwrid(smbpass, user_rid);
+ ret = pdb_getsampwsid(smbpass, user_sid);
unbecome_root();
if (ret==False) {
- DEBUG(4,("User 0x%x not found\n", user_rid));
- pdb_free_sam(&smbpass);
- return False;
+ DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
+ return NT_STATUS_NO_SUCH_USER;
}
DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) ));
@@ -1462,7 +1765,7 @@ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
pdb_free_sam(&smbpass);
- return True;
+ return NT_STATUS_OK;
}
/*************************************************************************
@@ -1471,10 +1774,11 @@ static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
user. JRA.
*************************************************************************/
-static NTSTATUS get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint32 user_rid)
+static NTSTATUS get_user_info_12(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_INFO_12 * id12, DOM_SID *user_sid)
{
SAM_ACCOUNT *smbpass=NULL;
BOOL ret;
+ NTSTATUS nt_status;
if (!p->ntlmssp_auth_validated)
return NT_STATUS_ACCESS_DENIED;
@@ -1485,12 +1789,17 @@ static NTSTATUS get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint3
/*
* Do *NOT* do become_root()/unbecome_root() here ! JRA.
*/
- pdb_init_sam(&smbpass);
- ret = pdb_getsampwrid(smbpass, user_rid);
+ nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ ret = pdb_getsampwsid(smbpass, user_sid);
if (ret == False) {
- DEBUG(4, ("User 0x%x not found\n", user_rid));
+ DEBUG(4, ("User %s not found\n", sid_string_static(user_sid)));
pdb_free_sam(&smbpass);
return (geteuid() == (uid_t)0) ? NT_STATUS_NO_SUCH_USER : NT_STATUS_ACCESS_DENIED;
}
@@ -1514,21 +1823,20 @@ static NTSTATUS get_user_info_12(pipes_struct *p, SAM_USER_INFO_12 * id12, uint3
get_user_info_20
*************************************************************************/
-static BOOL get_user_info_20(SAM_USER_INFO_20 *id20, uint32 user_rid)
+static NTSTATUS get_user_info_20(TALLOC_CTX *mem_ctx, SAM_USER_INFO_20 *id20, DOM_SID *user_sid)
{
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
- pdb_init_sam(&sampass);
+ pdb_init_sam_talloc(mem_ctx, &sampass);
become_root();
- ret = pdb_getsampwrid(sampass, user_rid);
+ ret = pdb_getsampwsid(sampass, user_sid);
unbecome_root();
if (ret == False) {
- DEBUG(4,("User 0x%x not found\n", user_rid));
- pdb_free_sam(&sampass);
- return False;
+ DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
+ return NT_STATUS_NO_SUCH_USER;
}
samr_clear_sam_passwd(sampass);
@@ -1540,28 +1848,32 @@ static BOOL get_user_info_20(SAM_USER_INFO_20 *id20, uint32 user_rid)
pdb_free_sam(&sampass);
- return True;
+ return NT_STATUS_OK;
}
/*************************************************************************
get_user_info_21
*************************************************************************/
-static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
+static NTSTATUS get_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21,
+ DOM_SID *user_sid, DOM_SID *domain_sid)
{
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
+ NTSTATUS nt_status;
- pdb_init_sam(&sampass);
+ nt_status = pdb_init_sam_talloc(mem_ctx, &sampass);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
become_root();
- ret = pdb_getsampwrid(sampass, user_rid);
+ ret = pdb_getsampwsid(sampass, user_sid);
unbecome_root();
if (ret == False) {
- DEBUG(4,("User 0x%x not found\n", user_rid));
- pdb_free_sam(&sampass);
- return False;
+ DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
+ return NT_STATUS_NO_SUCH_USER;
}
samr_clear_sam_passwd(sampass);
@@ -1569,11 +1881,11 @@ static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
DEBUG(3,("User:[%s]\n", pdb_get_username(sampass) ));
ZERO_STRUCTP(id21);
- init_sam_user_info21A(id21, sampass);
+ nt_status = init_sam_user_info21A(id21, sampass, domain_sid);
pdb_free_sam(&sampass);
- return True;
+ return NT_STATUS_OK;
}
/*******************************************************************
@@ -1583,21 +1895,24 @@ static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_QUERY_USERINFO *r_u)
{
SAM_USERINFO_CTR *ctr;
- uint32 rid = 0;
struct samr_info *info = NULL;
-
+ DOM_SID domain_sid;
+ uint32 rid;
+
r_u->status=NT_STATUS_OK;
/* search for the handle */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
+ domain_sid = info->sid;
+
+ sid_split_rid(&domain_sid, &rid);
+
if (!sid_check_is_in_our_domain(&info->sid))
return NT_STATUS_OBJECT_TYPE_MISMATCH;
- sid_peek_rid(&info->sid, &rid);
-
- DEBUG(5,("_samr_query_userinfo: rid:0x%x\n", rid));
+ DEBUG(5,("_samr_query_userinfo: sid:%s\n", sid_string_static(&info->sid)));
ctr = (SAM_USERINFO_CTR *)talloc_zero(p->mem_ctx, sizeof(SAM_USERINFO_CTR));
if (!ctr)
@@ -1614,8 +1929,8 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
if (ctr->info.id10 == NULL)
return NT_STATUS_NO_MEMORY;
- if (!get_user_info_10(ctr->info.id10, rid))
- return NT_STATUS_NO_SUCH_USER;
+ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_10(p->mem_ctx, ctr->info.id10, &info->sid)))
+ return r_u->status;
break;
#if 0
@@ -1649,24 +1964,25 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
if (ctr->info.id12 == NULL)
return NT_STATUS_NO_MEMORY;
- if (NT_STATUS_IS_ERR(r_u->status = get_user_info_12(p, ctr->info.id12, rid)))
+ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_12(p, p->mem_ctx, ctr->info.id12, &info->sid)))
return r_u->status;
break;
-
+
case 20:
ctr->info.id20 = (SAM_USER_INFO_20 *)talloc_zero(p->mem_ctx,sizeof(SAM_USER_INFO_20));
if (ctr->info.id20 == NULL)
return NT_STATUS_NO_MEMORY;
- if (!get_user_info_20(ctr->info.id20, rid))
- return NT_STATUS_NO_SUCH_USER;
+ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_20(p->mem_ctx, ctr->info.id20, &info->sid)))
+ return r_u->status;
break;
case 21:
ctr->info.id21 = (SAM_USER_INFO_21 *)talloc_zero(p->mem_ctx,sizeof(SAM_USER_INFO_21));
if (ctr->info.id21 == NULL)
return NT_STATUS_NO_MEMORY;
- if (!get_user_info_21(ctr->info.id21, rid))
- return NT_STATUS_NO_SUCH_USER;
+ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_21(p->mem_ctx, ctr->info.id21,
+ &info->sid, &domain_sid)))
+ return r_u->status;
break;
default:
@@ -1676,7 +1992,7 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
init_samr_r_query_userinfo(r_u, ctr, r_u->status);
DEBUG(5,("_samr_query_userinfo: %d\n", __LINE__));
-
+
return r_u->status;
}
@@ -1687,10 +2003,10 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
{
SAM_ACCOUNT *sam_pass=NULL;
+ DOM_SID sid;
DOM_GID *gids = NULL;
int num_groups = 0;
- uint32 rid;
- struct samr_info *info = NULL;
+ uint32 acc_granted;
BOOL ret;
/*
@@ -1710,37 +2026,39 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_usergroups"))) {
+ return r_u->status;
+ }
- if (!sid_check_is_in_our_domain(&info->sid))
+ if (!sid_check_is_in_our_domain(&sid))
return NT_STATUS_OBJECT_TYPE_MISMATCH;
- sid_peek_rid(&info->sid, &rid);
-
pdb_init_sam(&sam_pass);
-
+
become_root();
- ret = pdb_getsampwrid(sam_pass, rid);
+ ret = pdb_getsampwsid(sam_pass, &sid);
unbecome_root();
if (ret == False) {
pdb_free_sam(&sam_pass);
return NT_STATUS_NO_SUCH_USER;
}
-
+
if(!get_domain_user_groups(p->mem_ctx, &num_groups, &gids, sam_pass)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_NO_SUCH_GROUP;
}
-
+
/* construct the response. lkclXXXX: gids are not copied! */
init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status);
-
+
DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
pdb_free_sam(&sam_pass);
-
+
return r_u->status;
}
@@ -1771,13 +2089,13 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
ZERO_STRUCTP(ctr);
r_u->status = NT_STATUS_OK;
-
+
DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
-
+
/* find the policy handle. open a policy on it. */
if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
-
+
switch (q_u->switch_value) {
case 0x01:
account_policy_get(AP_MIN_PASSWORD_LEN, &min_pass_len);
@@ -1796,15 +2114,15 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
become_root();
r_u->status=load_sampwd_entries(info, ACB_NORMAL);
unbecome_root();
- if (NT_STATUS_IS_ERR(r_u->status)) {
+ if (!NT_STATUS_IS_OK(r_u->status)) {
DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
return r_u->status;
}
num_users=info->disp_info.num_user_account;
free_samr_db(info);
- r_u->status=load_group_domain_entries(info, &global_sam_sid);
- if (NT_STATUS_IS_ERR(r_u->status)) {
+ r_u->status=load_group_domain_entries(info, get_global_sam_sid());
+ if (!NT_STATUS_IS_OK(r_u->status)) {
DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
return r_u->status;
}
@@ -1842,12 +2160,12 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
break;
default:
return NT_STATUS_INVALID_INFO_CLASS;
- }
-
+ }
+
init_samr_r_query_dom_info(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
-
+
DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__));
-
+
return r_u->status;
}
@@ -1871,11 +2189,19 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
BOOL ret;
NTSTATUS nt_status;
struct passwd *pw;
+ uint32 acc_granted;
+ SEC_DESC *psd;
+ size_t sd_size;
+ uint32 des_access;
- /* find the policy handle. open a policy on it. */
- if (!find_policy_by_hnd(p, &dom_pol, NULL))
+ /* Get the domain SID stored in the domain policy */
+ if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+ if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_USER, "_samr_create_user"))) {
+ return nt_status;
+ }
+
/* find the account: tell the caller if it exists.
lkclXXXX i have *no* idea if this is a problem or not
or even if you are supposed to construct a different
@@ -1944,7 +2270,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
else
pstrcpy(add_script, lp_adduser_script());
- if(*add_script) {
+ if (*add_script) {
int add_ret;
all_string_sub(add_script, "%u", account, sizeof(account));
add_ret = smbrun(add_script,NULL);
@@ -1990,16 +2316,15 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
return NT_STATUS_ACCESS_DENIED;
}
- /* Get the domain SID stored in the domain policy */
- if(!get_lsa_policy_samr_sid(p, &dom_pol, &sid)) {
- pdb_free_sam(&sam_pass);
- return NT_STATUS_INVALID_HANDLE;
- }
-
- /* append the user's RID to it */
- if(!sid_append_rid(&sid, pdb_get_user_rid(sam_pass) )) {
- pdb_free_sam(&sam_pass);
- return NT_STATUS_NO_SUCH_USER;
+ /* Get the user's SID */
+ sid_copy(&sid, pdb_get_user_sid(sam_pass));
+
+ samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid);
+ se_map_generic(&des_access, &usr_generic_mapping);
+ if (!NT_STATUS_IS_OK(nt_status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_create_user"))) {
+ return nt_status;
}
/* associate the user's SID with the new handle. */
@@ -2010,6 +2335,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_
ZERO_STRUCTP(info);
info->sid = sid;
+ info->acc_granted = acc_granted;
/* get a (unique) handle. open a policy on it. */
if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) {
@@ -2033,21 +2359,29 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
{
struct samr_info *info = NULL;
- /* set up the SAMR connect_anon response */
+ /* Access check */
- r_u->status = NT_STATUS_OK;
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to samr_connect_anon\n"));
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ return r_u->status;
+ }
- /* associate the user's SID with the new handle. */
- if ((info = get_samr_info_by_sid(NULL)) == NULL)
- return NT_STATUS_NO_MEMORY;
+ /* set up the SAMR connect_anon response */
- info->status = q_u->unknown_0;
+ r_u->status = NT_STATUS_OK;
- /* get a (unique) handle. open a policy on it. */
- if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ /* associate the user's SID with the new handle. */
+ if ((info = get_samr_info_by_sid(NULL)) == NULL)
+ return NT_STATUS_NO_MEMORY;
- return r_u->status;
+ info->status = q_u->unknown_0;
+
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+
+ return r_u->status;
}
/*******************************************************************
@@ -2057,24 +2391,47 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO
NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u)
{
struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->access_mask;
+ size_t sd_size;
+ NTSTATUS nt_status;
- DEBUG(5,("_samr_connect: %d\n", __LINE__));
- r_u->status = NT_STATUS_OK;
+ DEBUG(5,("_samr_connect: %d\n", __LINE__));
+
+ /* Access check */
+
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to samr_connect\n"));
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ return r_u->status;
+ }
+
+ samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ se_map_generic(&des_access, &sam_generic_mapping);
+ if (!NT_STATUS_IS_OK(nt_status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_connect"))) {
+ return nt_status;
+ }
- /* associate the user's SID with the new handle. */
+ r_u->status = NT_STATUS_OK;
+
+ /* associate the user's SID and access granted with the new handle. */
if ((info = get_samr_info_by_sid(NULL)) == NULL)
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_NO_MEMORY;
- info->status = q_u->access_mask;
+ info->acc_granted = acc_granted;
+ info->status = q_u->access_mask;
- /* get a (unique) handle. open a policy on it. */
- if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ /* get a (unique) handle. open a policy on it. */
+ if (!create_policy_hnd(p, &r_u->connect_pol, free_samr_info, (void *)info))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(5,("_samr_connect: %d\n", __LINE__));
+ DEBUG(5,("_samr_connect: %d\n", __LINE__));
- return r_u->status;
+ return r_u->status;
}
/**********************************************************************
@@ -2083,14 +2440,19 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u)
{
+ struct samr_info *info;
fstring domain_name;
DOM_SID sid;
r_u->status = NT_STATUS_OK;
- if (!find_policy_by_hnd(p, &q_u->connect_pol, NULL))
+ if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)&info))
return NT_STATUS_INVALID_HANDLE;
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_OPEN_DOMAIN, "_samr_lookup_domain"))) {
+ return r_u->status;
+ }
+
rpcstr_pull(domain_name, q_u->uni_domain.buffer, sizeof(domain_name), q_u->uni_domain.uni_str_len*2, 0);
ZERO_STRUCT(sid);
@@ -2150,11 +2512,19 @@ static BOOL make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam,
NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_ENUM_DOMAINS *r_u)
{
+ struct samr_info *info;
uint32 num_entries = 2;
fstring dom[2];
char *name;
r_u->status = NT_STATUS_OK;
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void**)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SAMR_ACCESS_ENUM_DOMAINS, "_samr_enum_domains"))) {
+ return r_u->status;
+ }
switch (lp_server_role()) {
case ROLE_DOMAIN_PDC:
@@ -2187,21 +2557,35 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
POLICY_HND domain_pol = q_u->dom_pol;
uint32 alias_rid = q_u->rid_alias;
POLICY_HND *alias_pol = &r_u->pol;
- struct samr_info *info = NULL;
+ struct samr_info *info = NULL;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access = q_u->access_mask;
+ size_t sd_size;
+ NTSTATUS status;
r_u->status = NT_STATUS_OK;
- /* get the domain policy. */
- if (!find_policy_by_hnd(p, &domain_pol, NULL))
- return NT_STATUS_INVALID_HANDLE;
-
- /* Get the domain SID stored in the domain policy */
- if(!get_lsa_policy_samr_sid(p, &domain_pol, &sid))
+ /* find the domain policy and get the SID / access bits stored in the domain policy */
+ if (!get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_alias"))) {
+ return status;
+ }
/* append the alias' RID to it */
- if(!sid_append_rid(&sid, alias_rid))
+ if (!sid_append_rid(&sid, alias_rid))
return NT_STATUS_NO_SUCH_USER;
+
+ /*check if access can be granted as requested by client. */
+ samr_make_ali_obj_sd(p->mem_ctx, &psd, &sd_size);
+ se_map_generic(&des_access,&ali_generic_mapping);
+ if (!NT_STATUS_IS_OK(status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_open_alias"))) {
+ return status;
+ }
/*
* we should check if the rid really exist !!!
@@ -2211,6 +2595,8 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
/* associate the user's SID with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL)
return NT_STATUS_NO_MEMORY;
+
+ info->acc_granted = acc_granted;
/* get a (unique) handle. open a policy on it. */
if (!create_policy_hnd(p, alias_pol, free_samr_info, (void *)info))
@@ -2223,14 +2609,14 @@ NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OP
set_user_info_10
********************************************************************/
-static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, uint32 rid)
+static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid)
{
SAM_ACCOUNT *pwd =NULL;
BOOL ret;
pdb_init_sam(&pwd);
- ret = pdb_getsampwrid(pwd, rid);
+ ret = pdb_getsampwsid(pwd, sid);
if(ret==False) {
pdb_free_sam(&pwd);
@@ -2262,13 +2648,13 @@ static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, uint32 rid)
set_user_info_12
********************************************************************/
-static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, uint32 rid)
+static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid)
{
SAM_ACCOUNT *pwd = NULL;
pdb_init_sam(&pwd);
- if(!pdb_getsampwrid(pwd, rid)) {
+ if(!pdb_getsampwsid(pwd, sid)) {
pdb_free_sam(&pwd);
return False;
}
@@ -2305,7 +2691,7 @@ static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, uint32 rid)
set_user_info_21
********************************************************************/
-static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid)
+static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid)
{
SAM_ACCOUNT *pwd = NULL;
@@ -2316,7 +2702,7 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid)
pdb_init_sam(&pwd);
- if (!pdb_getsampwrid(pwd, rid)) {
+ if (!pdb_getsampwsid(pwd, sid)) {
pdb_free_sam(&pwd);
return False;
}
@@ -2345,7 +2731,7 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, uint32 rid)
set_user_info_23
********************************************************************/
-static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
+static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
{
SAM_ACCOUNT *pwd = NULL;
pstring plaintext_buf;
@@ -2359,7 +2745,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
pdb_init_sam(&pwd);
- if (!pdb_getsampwrid(pwd, rid)) {
+ if (!pdb_getsampwsid(pwd, sid)) {
pdb_free_sam(&pwd);
return False;
}
@@ -2412,7 +2798,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, uint32 rid)
set_user_info_pw
********************************************************************/
-static BOOL set_user_info_pw(char *pass, uint32 rid)
+static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
{
SAM_ACCOUNT *pwd = NULL;
uint32 len;
@@ -2421,7 +2807,7 @@ static BOOL set_user_info_pw(char *pass, uint32 rid)
pdb_init_sam(&pwd);
- if (!pdb_getsampwrid(pwd, rid)) {
+ if (!pdb_getsampwsid(pwd, sid)) {
pdb_free_sam(&pwd);
return False;
}
@@ -2480,23 +2866,27 @@ static BOOL set_user_info_pw(char *pass, uint32 rid)
NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u)
{
- uint32 rid = 0x0;
DOM_SID sid;
POLICY_HND *pol = &q_u->pol;
uint16 switch_value = q_u->switch_value;
SAM_USERINFO_CTR *ctr = q_u->ctr;
+ uint32 acc_granted;
+ uint32 acc_required;
DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
- sid_split_rid(&sid, &rid);
-
- DEBUG(5, ("_samr_set_userinfo: rid:0x%x, level:%d\n", rid, switch_value));
+
+ acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) {
+ return r_u->status;
+ }
+
+ DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value));
if (ctr == NULL) {
DEBUG(5, ("_samr_set_userinfo: NULL info level\n"));
@@ -2506,7 +2896,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch (switch_value) {
case 0x12:
- if (!set_user_info_12(ctr->info.id12, rid))
+ if (!set_user_info_12(ctr->info.id12, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
@@ -2515,7 +2905,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id24->pass, 516);
- if (!set_user_info_pw((char *)ctr->info.id24->pass, rid))
+ if (!set_user_info_pw((char *)ctr->info.id24->pass, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
@@ -2533,7 +2923,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id25->pass, 532);
- if (!set_user_info_pw(ctr->info.id25->pass, rid))
+ if (!set_user_info_pw(ctr->info.id25->pass, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
#endif
@@ -2544,7 +2934,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
dump_data(100, (char *)ctr->info.id23->pass, 516);
- if (!set_user_info_23(ctr->info.id23, rid))
+ if (!set_user_info_23(ctr->info.id23, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
@@ -2562,22 +2952,26 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_SET_USERINFO2 *r_u)
{
DOM_SID sid;
- uint32 rid = 0x0;
SAM_USERINFO_CTR *ctr = q_u->ctr;
POLICY_HND *pol = &q_u->pol;
uint16 switch_value = q_u->switch_value;
+ uint32 acc_granted;
+ uint32 acc_required;
DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ acc_required = USER_ACCESS_SET_LOC_COM | USER_ACCESS_SET_ATTRIBUTES; /* This is probably wrong */
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo2"))) {
+ return r_u->status;
+ }
- sid_split_rid(&sid, &rid);
-
- DEBUG(5, ("samr_reply_set_userinfo2: rid:0x%x\n", rid));
+ DEBUG(5, ("samr_reply_set_userinfo2: sid:%s\n", sid_string_static(&sid)));
if (ctr == NULL) {
DEBUG(5, ("samr_reply_set_userinfo2: NULL info level\n"));
@@ -2589,16 +2983,16 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch (switch_value) {
case 21:
- if (!set_user_info_21(ctr->info.id21, rid))
+ if (!set_user_info_21(ctr->info.id21, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
case 16:
- if (!set_user_info_10(ctr->info.id10, rid))
+ if (!set_user_info_10(ctr->info.id10, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
case 18:
/* Used by AS/U JRA. */
- if (!set_user_info_12(ctr->info.id12, rid))
+ if (!set_user_info_12(ctr->info.id12, &sid))
return NT_STATUS_ACCESS_DENIED;
break;
default:
@@ -2642,6 +3036,10 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
/* find the policy handle. open a policy on it. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, USER_ACCESS_GET_GROUPS, "_samr_query_useraliases"))) {
+ return r_u->status;
+ }
if (!sid_check_is_domain(&info->sid) &&
!sid_check_is_builtin(&info->sid))
@@ -2656,7 +3054,7 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
* if there is an error, we just continue as
* it can be an unfound user or group
*/
- if (NT_STATUS_IS_ERR(r_u->status)) {
+ if (!NT_STATUS_IS_OK(r_u->status)) {
DEBUG(10,("_samr_query_useraliases: an error occured while getting groups\n"));
continue;
}
@@ -2706,11 +3104,16 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
SAM_ACCOUNT *sam_user = NULL;
BOOL check;
+ uint32 acc_granted;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_GET_MEMBERS, "_samr_query_aliasmem"))) {
+ return r_u->status;
+ }
+
sid_copy(&als_sid, &alias_sid);
sid_to_string(alias_sid_str, &alias_sid);
sid_split_rid(&alias_sid, &alias_rid);
@@ -2722,7 +3125,7 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
if(!get_local_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_ALIAS;
} else {
- if (sid_equal(&alias_sid, &global_sam_sid)) {
+ if (sid_equal(&alias_sid, get_global_sam_sid())) {
DEBUG(10, ("lookup on Server SID\n"));
if(!get_local_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_ALIAS;
@@ -2741,12 +3144,12 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
struct passwd *pass;
uint32 rid;
- sid_copy(&temp_sid, &global_sam_sid);
+ sid_copy(&temp_sid, get_global_sam_sid());
pass = getpwuid_alloc(uid[i]);
if (!pass) continue;
- if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) {
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_user))) {
passwd_free(&pass);
continue;
}
@@ -2802,12 +3205,16 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
SAM_ACCOUNT *sam_user = NULL;
BOOL check;
-
+ uint32 acc_granted;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_GET_MEMBERS, "_samr_query_groupmem"))) {
+ return r_u->status;
+ }
+
/* todo: change to use sid_compare_front */
sid_split_rid(&group_sid, &group_rid);
@@ -2815,7 +3222,7 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
DEBUG(10, ("sid is %s\n", group_sid_str));
/* can we get a query for an SID outside our domain ? */
- if (!sid_equal(&group_sid, &global_sam_sid))
+ if (!sid_equal(&group_sid, get_global_sam_sid()))
return NT_STATUS_NO_SUCH_GROUP;
sid_append_rid(&group_sid, group_rid);
@@ -2840,7 +3247,7 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
pass = getpwuid_alloc(uid[i]);
if (!pass) continue;
- if (NT_STATUS_IS_ERR(pdb_init_sam(&sam_user))) {
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_user))) {
passwd_free(&pass);
continue;
}
@@ -2886,20 +3293,24 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
struct passwd *pwd;
struct group *grp;
fstring grp_name;
- uint32 rid;
GROUP_MAP map;
NTSTATUS ret;
SAM_ACCOUNT *sam_user = NULL;
BOOL check;
+ uint32 acc_granted;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_ADD_MEMBER, "_samr_add_aliasmem"))) {
+ return r_u->status;
+ }
+
sid_to_string(alias_sid_str, &alias_sid);
DEBUG(10, ("sid is %s\n", alias_sid_str));
- if (sid_compare(&alias_sid, &global_sam_sid)>0) {
+ if (sid_compare(&alias_sid, get_global_sam_sid())>0) {
DEBUG(10, ("adding member on Server SID\n"));
if(!get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_ALIAS;
@@ -2914,13 +3325,11 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
return NT_STATUS_NO_SUCH_ALIAS;
}
- sid_split_rid(&q_u->sid.sid, &rid);
-
ret = pdb_init_sam(&sam_user);
- if (NT_STATUS_IS_ERR(ret))
+ if (!NT_STATUS_IS_OK(ret))
return ret;
- check = pdb_getsampwrid(sam_user, rid);
+ check = pdb_getsampwsid(sam_user, &q_u->sid.sid);
if (check != True) {
pdb_free_sam(&sam_user);
@@ -2935,8 +3344,11 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
pdb_free_sam(&sam_user);
- if ((pwd=getpwuid(uid)) == NULL)
+ if ((pwd=getpwuid_alloc(uid)) == NULL) {
return NT_STATUS_NO_SUCH_USER;
+ } else {
+ passwd_free(&pwd);
+ }
if ((grp=getgrgid(map.gid)) == NULL)
return NT_STATUS_NO_SUCH_ALIAS;
@@ -2971,14 +3383,18 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
fstring alias_sid_str;
struct group *grp;
fstring grp_name;
- uint32 rid;
GROUP_MAP map;
SAM_ACCOUNT *sam_pass=NULL;
+ uint32 acc_granted;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_REMOVE_MEMBER, "_samr_del_aliasmem"))) {
+ return r_u->status;
+ }
+
sid_to_string(alias_sid_str, &alias_sid);
DEBUG(10, ("_samr_del_aliasmem:sid is %s\n", alias_sid_str));
@@ -2997,11 +3413,9 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
/* we need to copy the name otherwise it's overloaded in user_in_group_list */
fstrcpy(grp_name, grp->gr_name);
- sid_peek_rid(&q_u->sid.sid, &rid);
-
/* check if the user exists before trying to remove it from the group */
pdb_init_sam(&sam_pass);
- if(!pdb_getsampwrid(sam_pass, rid)) {
+ if(!pdb_getsampwsid(sam_pass, &q_u->sid.sid)) {
DEBUG(5,("_samr_del_aliasmem:User %s doesn't exist.\n", pdb_get_username(sam_pass)));
pdb_free_sam(&sam_pass);
return NT_STATUS_NO_SUCH_USER;
@@ -3032,6 +3446,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_ADD_GROUPMEM *r_u)
{
DOM_SID group_sid;
+ DOM_SID user_sid;
fstring group_sid_str;
struct passwd *pwd;
struct group *grp;
@@ -3041,15 +3456,20 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
NTSTATUS ret;
SAM_ACCOUNT *sam_user;
BOOL check;
+ uint32 acc_granted;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_ADD_MEMBER, "_samr_add_groupmem"))) {
+ return r_u->status;
+ }
sid_to_string(group_sid_str, &group_sid);
DEBUG(10, ("sid is %s\n", group_sid_str));
- if (sid_compare(&group_sid, &global_sam_sid)<=0)
+ if (sid_compare(&group_sid, get_global_sam_sid())<=0)
return NT_STATUS_NO_SUCH_GROUP;
DEBUG(10, ("lookup on Domain SID\n"));
@@ -3057,11 +3477,14 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_GROUP;
+ sid_copy(&user_sid, get_global_sam_sid());
+ sid_append_rid(&user_sid, q_u->rid);
+
ret = pdb_init_sam(&sam_user);
- if (NT_STATUS_IS_ERR(ret))
+ if (!NT_STATUS_IS_OK(ret))
return ret;
- check = pdb_getsampwrid(sam_user, q_u->rid);
+ check = pdb_getsampwsid(sam_user, &user_sid);
if (check != True) {
pdb_free_sam(&sam_user);
@@ -3076,8 +3499,11 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
pdb_free_sam(&sam_user);
- if ((pwd=getpwuid(uid)) == NULL)
+ if ((pwd=getpwuid_alloc(uid)) == NULL) {
return NT_STATUS_NO_SUCH_USER;
+ } else {
+ passwd_free(&pwd);
+ }
if ((grp=getgrgid(map.gid)) == NULL)
return NT_STATUS_NO_SUCH_GROUP;
@@ -3111,11 +3537,12 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DEL_GROUPMEM *r_u)
{
DOM_SID group_sid;
+ DOM_SID user_sid;
SAM_ACCOUNT *sam_pass=NULL;
- uint32 rid;
GROUP_MAP map;
fstring grp_name;
struct group *grp;
+ uint32 acc_granted;
/*
* delete the group member named q_u->rid
@@ -3124,15 +3551,20 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
*/
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
- if(!sid_check_is_in_our_domain(&group_sid))
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_REMOVE_MEMBER, "_samr_del_groupmem"))) {
+ return r_u->status;
+ }
+
+ if (!sid_check_is_in_our_domain(&group_sid))
return NT_STATUS_NO_SUCH_GROUP;
- rid=q_u->rid;
+ sid_copy(&user_sid, get_global_sam_sid());
+ sid_append_rid(&user_sid, q_u->rid);
- if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
+ if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_NO_SUCH_GROUP;
if ((grp=getgrgid(map.gid)) == NULL)
@@ -3143,14 +3575,14 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
/* check if the user exists before trying to remove it from the group */
pdb_init_sam(&sam_pass);
- if(!pdb_getsampwrid(sam_pass, rid)) {
+ if (!pdb_getsampwsid(sam_pass, &user_sid)) {
DEBUG(5,("User %s doesn't exist.\n", pdb_get_username(sam_pass)));
pdb_free_sam(&sam_pass);
return NT_STATUS_NO_SUCH_USER;
}
/* if the user is not in the group */
- if(!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if (!user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_MEMBER_NOT_IN_GROUP;
}
@@ -3158,7 +3590,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
smb_delete_user_group(grp_name, pdb_get_username(sam_pass));
/* check if the user has been removed then ... */
- if(user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
+ if (user_in_group_list(pdb_get_username(sam_pass), grp_name)) {
pdb_free_sam(&sam_pass);
return NT_STATUS_ACCESS_DENIED; /* don't know what to reply else */
}
@@ -3168,6 +3600,24 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
}
+/****************************************************************************
+ Delete a UNIX user on demand.
+****************************************************************************/
+
+static int smb_delete_user(const char *unix_user)
+{
+ pstring del_script;
+ int ret;
+
+ pstrcpy(del_script, lp_deluser_script());
+ if (! *del_script)
+ return -1;
+ all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
+ ret = smbrun(del_script,NULL);
+ DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+ return ret;
+}
+
/*********************************************************************
_samr_delete_dom_user
*********************************************************************/
@@ -3176,22 +3626,24 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
{
DOM_SID user_sid;
SAM_ACCOUNT *sam_pass=NULL;
- uint32 rid;
+ uint32 acc_granted;
DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_user"))) {
+ return r_u->status;
+ }
+
if (!sid_check_is_in_our_domain(&user_sid))
return NT_STATUS_CANNOT_DELETE;
- sid_peek_rid(&user_sid, &rid);
-
/* check if the user exists before trying to delete */
pdb_init_sam(&sam_pass);
- if(!pdb_getsampwrid(sam_pass, rid)) {
+ if(!pdb_getsampwsid(sam_pass, &user_sid)) {
DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", pdb_get_username(sam_pass)));
pdb_free_sam(&sam_pass);
return NT_STATUS_NO_SUCH_USER;
@@ -3233,13 +3685,18 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
gid_t gid;
struct group *grp;
GROUP_MAP map;
+ uint32 acc_granted;
DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_group"))) {
+ return r_u->status;
+ }
+
sid_copy(&dom_sid, &group_sid);
sid_to_string(group_sid_str, &dom_sid);
sid_split_rid(&dom_sid, &group_rid);
@@ -3247,7 +3704,7 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
DEBUG(10, ("sid is %s\n", group_sid_str));
/* we check if it's our SID before deleting */
- if (!sid_equal(&dom_sid, &global_sam_sid))
+ if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_NO_SUCH_GROUP;
DEBUG(10, ("lookup on Domain SID\n"));
@@ -3290,13 +3747,18 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
gid_t gid;
struct group *grp;
GROUP_MAP map;
+ uint32 acc_granted;
DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DELETE_ACCESS, "_samr_delete_dom_alias"))) {
+ return r_u->status;
+ }
+
sid_copy(&dom_sid, &alias_sid);
sid_to_string(alias_sid_str, &dom_sid);
sid_split_rid(&dom_sid, &alias_rid);
@@ -3304,7 +3766,7 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
DEBUG(10, ("sid is %s\n", alias_sid_str));
/* we check if it's our SID before deleting */
- if (!sid_equal(&dom_sid, &global_sam_sid))
+ if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_NO_SUCH_ALIAS;
DEBUG(10, ("lookup on Local SID\n"));
@@ -3347,14 +3809,19 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
struct group *grp;
struct samr_info *info;
PRIVILEGE_SET priv_set;
+ uint32 acc_granted;
init_privilege(&priv_set);
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
- if (!sid_equal(&dom_sid, &global_sam_sid))
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_GROUP, "_samr_create_dom_group"))) {
+ return r_u->status;
+ }
+
+ if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;
/* TODO: check if allowed to create group and add a become_root/unbecome_root pair.*/
@@ -3375,7 +3842,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
/* add the group to the mapping table */
- sid_copy(&info_sid, &global_sam_sid);
+ sid_copy(&info_sid, get_global_sam_sid());
sid_append_rid(&info_sid, r_u->rid);
sid_to_string(sid_string, &info_sid);
@@ -3405,14 +3872,19 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
struct group *grp;
struct samr_info *info;
PRIVILEGE_SET priv_set;
+ uint32 acc_granted;
init_privilege(&priv_set);
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
- if (!sid_equal(&dom_sid, &global_sam_sid))
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_CREATE_ALIAS, "_samr_create_alias"))) {
+ return r_u->status;
+ }
+
+ if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;
/* TODO: check if allowed to create group and add a become_root/unbecome_root pair.*/
@@ -3432,7 +3904,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
- sid_copy(&info_sid, &global_sam_sid);
+ sid_copy(&info_sid, get_global_sam_sid());
sid_append_rid(&info_sid, r_u->rid);
sid_to_string(sid_string, &info_sid);
@@ -3464,10 +3936,15 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
uid_t *uid=NULL;
int num_uids=0;
GROUP_INFO_CTR *ctr;
+ uint32 acc_granted;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_LOOKUP_INFO, "_samr_query_groupinfo"))) {
+ return r_u->status;
+ }
+
if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV))
return NT_STATUS_INVALID_HANDLE;
@@ -3511,10 +3988,15 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
DOM_SID group_sid;
GROUP_MAP map;
GROUP_INFO_CTR *ctr;
+ uint32 acc_granted;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, GROUP_ACCESS_SET_INFO, "_samr_set_groupinfo"))) {
+ return r_u->status;
+ }
+
if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
return NT_STATUS_NO_SUCH_GROUP;
@@ -3553,10 +4035,15 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
DOM_SID group_sid;
GROUP_MAP map;
ALIAS_INFO_CTR *ctr;
+ uint32 acc_granted;
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
-
+
+ if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, ALIAS_ACCESS_SET_INFO, "_samr_set_aliasinfo"))) {
+ return r_u->status;
+ }
+
if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV))
return NT_STATUS_NO_SUCH_GROUP;
@@ -3587,7 +4074,18 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
NTSTATUS _samr_get_dom_pwinfo(pipes_struct *p, SAMR_Q_GET_DOM_PWINFO *q_u, SAMR_R_GET_DOM_PWINFO *r_u)
{
+ /* Perform access check. Since this rpc does not require a
+ policy handle it will not be caught by the access checks on
+ SAMR_CONNECT or SAMR_CONNECT_ANON. */
+
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to samr_get_dom_pwinfo\n"));
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ return r_u->status;
+ }
+
/* Actually, returning zeros here works quite well :-). */
+
return NT_STATUS_OK;
}
@@ -3601,21 +4099,42 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
DOM_SID info_sid;
GROUP_MAP map;
struct samr_info *info;
+ SEC_DESC *psd = NULL;
+ uint32 acc_granted;
+ uint32 des_access;
+ size_t sd_size;
+ NTSTATUS status;
fstring sid_string;
- if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid))
+ if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
+
+ if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, DOMAIN_ACCESS_OPEN_ACCOUNT, "_samr_open_group"))) {
+ return status;
+ }
+
+ /*check if access can be granted as requested by client. */
+ samr_make_grp_obj_sd(p->mem_ctx, &psd, &sd_size);
+ se_map_generic(&des_access,&grp_generic_mapping);
+ if (!NT_STATUS_IS_OK(status =
+ access_check_samr_object(psd, p->pipe_user.nt_user_token,
+ des_access, &acc_granted, "_samr_open_group"))) {
+ return status;
+ }
+
/* this should not be hard-coded like this */
- if (!sid_equal(&sid, &global_sam_sid))
+ if (!sid_equal(&sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;
- sid_copy(&info_sid, &global_sam_sid);
+ sid_copy(&info_sid, get_global_sam_sid());
sid_append_rid(&info_sid, q_u->rid_group);
sid_to_string(sid_string, &info_sid);
if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
return NT_STATUS_NO_MEMORY;
+
+ info->acc_granted = acc_granted;
DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string));
@@ -3692,14 +4211,14 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
become_root();
r_u->status=load_sampwd_entries(info, ACB_NORMAL);
unbecome_root();
- if (NT_STATUS_IS_ERR(r_u->status)) {
+ if (!NT_STATUS_IS_OK(r_u->status)) {
DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
return r_u->status;
}
num_users=info->disp_info.num_user_account;
free_samr_db(info);
- r_u->status=load_group_domain_entries(info, &global_sam_sid);
+ r_u->status=load_group_domain_entries(info, get_global_sam_sid());
if (NT_STATUS_IS_ERR(r_u->status)) {
DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
return r_u->status;
diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c
index c7dc5d27ff..6e3463e79b 100755
--- a/source3/rpc_server/srv_spoolss.c
+++ b/source3/rpc_server/srv_spoolss.c
@@ -4,7 +4,8 @@
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Jean François Micouleau 1998-2000.
- * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Gerald Carter 2001-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
@@ -23,6 +24,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/********************************************************************
* api_spoolss_open_printer_ex (rarely seen - older call)
********************************************************************/
@@ -1399,6 +1403,119 @@ static BOOL api_spoolss_getprintprocessordirectory(pipes_struct *p)
return True;
}
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_deleteprinterdataex(pipes_struct *p)
+{
+ SPOOL_Q_DELETEPRINTERDATAEX q_u;
+ SPOOL_R_DELETEPRINTERDATAEX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_deleteprinterdataex("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_deleteprinterdataex: unable to unmarshall SPOOL_Q_DELETEPRINTERDATAEX.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_deleteprinterdataex(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_deleteprinterdataex("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_deleteprinterdataex: unable to marshall SPOOL_R_DELETEPRINTERDATAEX.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_deleteprinterkey(pipes_struct *p)
+{
+ SPOOL_Q_DELETEPRINTERKEY q_u;
+ SPOOL_R_DELETEPRINTERKEY r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_deleteprinterkey("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_deleteprinterkey: unable to unmarshall SPOOL_Q_DELETEPRINTERKEY.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_deleteprinterkey(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_deleteprinterkey("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_deleteprinterkey: unable to marshall SPOOL_R_DELETEPRINTERKEY.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_addprinterdriverex(pipes_struct *p)
+{
+ SPOOL_Q_ADDPRINTERDRIVEREX q_u;
+ SPOOL_R_ADDPRINTERDRIVEREX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_addprinterdriverex("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_addprinterdriverex: unable to unmarshall SPOOL_Q_ADDPRINTERDRIVEREX.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_addprinterdriverex(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_addprinterdriverex("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_addprinterdriverex: unable to marshall SPOOL_R_ADDPRINTERDRIVEREX.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL api_spoolss_deleteprinterdriverex(pipes_struct *p)
+{
+ SPOOL_Q_DELETEPRINTERDRIVEREX q_u;
+ SPOOL_R_DELETEPRINTERDRIVEREX r_u;
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!spoolss_io_q_deleteprinterdriverex("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_deleteprinterdriverex: unable to unmarshall SPOOL_Q_DELETEPRINTERDRIVEREX.\n"));
+ return False;
+ }
+
+ r_u.status = _spoolss_deleteprinterdriverex(p, &q_u, &r_u);
+
+ if(!spoolss_io_r_deleteprinterdriverex("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_deleteprinterdriverex: unable to marshall SPOOL_R_DELETEPRINTERDRIVEREX.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+
/*******************************************************************
\pipe\spoolss commands
********************************************************************/
@@ -1449,9 +1566,13 @@ struct api_struct api_spoolss_cmds[] =
{"SPOOLSS_ENUMPRINTPROCDATATYPES", SPOOLSS_ENUMPRINTPROCDATATYPES, api_spoolss_enumprintprocdatatypes },
{"SPOOLSS_GETPRINTERDATAEX", SPOOLSS_GETPRINTERDATAEX, api_spoolss_getprinterdataex },
{"SPOOLSS_SETPRINTERDATAEX", SPOOLSS_SETPRINTERDATAEX, api_spoolss_setprinterdataex },
- {"SPOOLSS_ENUMPRINTERKEY", SPOOLSS_ENUMPRINTERKEY, api_spoolss_enumprinterkey },
+ {"SPOOLSS_DELETEPRINTERDATAEX", SPOOLSS_DELETEPRINTERDATAEX, api_spoolss_deleteprinterdataex },
{"SPOOLSS_ENUMPRINTERDATAEX", SPOOLSS_ENUMPRINTERDATAEX, api_spoolss_enumprinterdataex },
+ {"SPOOLSS_ENUMPRINTERKEY", SPOOLSS_ENUMPRINTERKEY, api_spoolss_enumprinterkey },
+ {"SPOOLSS_DELETEPRINTERKEY", SPOOLSS_DELETEPRINTERKEY, api_spoolss_deleteprinterkey },
{"SPOOLSS_GETPRINTPROCESSORDIRECTORY",SPOOLSS_GETPRINTPROCESSORDIRECTORY,api_spoolss_getprintprocessordirectory},
+ {"SPOOLSS_ADDPRINTERDRIVEREX", SPOOLSS_ADDPRINTERDRIVEREX, api_spoolss_addprinterdriverex },
+ {"SPOOLSS_DELETEPRINTERDRIVEREX", SPOOLSS_DELETEPRINTERDRIVEREX, api_spoolss_deleteprinterdriverex },
{ NULL, 0, NULL }
};
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 322efa22b5..68c792f8b0 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -5,7 +5,7 @@
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Jean François Micouleau 1998-2000,
* Copyright (C) Jeremy Allison 2001,
- * Copyright (C) Gerald Carter 2000-2001,
+ * Copyright (C) Gerald Carter 2000-2002,
* Copyright (C) Tim Potter 2001-2002.
*
* This program is free software; you can redistribute it and/or modify
@@ -28,6 +28,10 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+/* #define EMULATE_WIN2K_HACK 1 */
+
#ifndef MAX_OPEN_PRINTER_EXS
#define MAX_OPEN_PRINTER_EXS 50
#endif
@@ -37,6 +41,15 @@
#define PRINTER_HANDLE_IS_PRINTER 0
#define PRINTER_HANDLE_IS_PRINTSERVER 1
+/* Table to map the driver version */
+/* to OS */
+char * drv_ver_to_os[] = {
+ "WIN9X", /* driver version/cversion 0 */
+ "", /* unused ? */
+ "WINNT", /* driver version/cversion 2 */
+ "WIN2K", /* driver version/cversion 3 */
+};
+
struct table_node {
char *long_archi;
char *short_archi;
@@ -68,6 +81,7 @@ typedef struct _Printer{
SPOOL_NOTIFY_OPTION *option;
POLICY_HND client_hnd;
uint32 client_connected;
+ uint32 change;
} notify;
struct {
fstring machine;
@@ -178,10 +192,10 @@ static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
/* if it's the last connection, deconnect the IPC$ share */
if (smb_connections==1) {
- if(!spoolss_disconnect_from_client(&cli))
- return;
-
- message_deregister(MSG_PRINTER_NOTIFY);
+ cli_nt_session_close(&cli);
+ cli_ulogoff(&cli);
+ cli_shutdown(&cli);
+ message_deregister(MSG_PRINTER_NOTIFY2);
}
smb_connections--;
@@ -426,7 +440,7 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
* anymore, so I've simplified this loop greatly. Here
* we are just verifying that the printer name is a valid
* printer service defined in smb.conf
- * --jerry [Fri Feb 15 11:17:46 CST 2002]
+ * --jerry [Fri Feb 15 11:17:46 CST 2002]
*/
for (snum=0; snum<n_services; snum++) {
@@ -535,229 +549,417 @@ static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
return True;
}
+
/***************************************************************************
- Always give preference Printer_entry.notify.option over
- Printer_entry.notify.flags. Return True if we should send notification
- events using SPOOLSS_RRPCN. False means that we should use
- SPOOLSS_ROUTERREPLYPRINTER.
+ check to see if the client motify handle is monitoring the notification
+ given by (notify_type, notify_field).
**************************************************************************/
-static BOOL valid_notify_options(Printer_entry *printer)
+
+static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
+ uint16 notify_field)
{
- if (printer->notify.option == NULL)
- return False;
-
return True;
}
-/***************************************************************************
- Simple check to see if the client motify handle is set to watch for events
- represented by 'flags'
-
- FIXME!!!! only a stub right now --jerry
- **************************************************************************/
-
-static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
+static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
+ uint16 notify_field)
{
+ SPOOL_NOTIFY_OPTION *option = p->notify.option;
+ uint32 i, j;
+
+ if (p->notify.flags)
+ return is_monitoring_event_flags(
+ p->notify.flags, notify_type, notify_field);
- return True;
-}
+ for (i = 0; i < option->count; i++) {
+
+ /* Check match for notify_type */
+
+ if (option->ctr.type[i].type != notify_type)
+ continue;
-/***************************************************************************
- Server wrapper for cli_spoolss_routerreplyprinter() since the client
- function can only send a single change notification at a time.
-
- FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
- --jerry
- **************************************************************************/
-
-static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
- NT_PRINTER_INFO_LEVEL *printer)
-{
- WERROR result;
- uint32 condition = 0x0;
+ /* Check match for field */
+
+ for (j = 0; j < option->ctr.type[i].count; j++) {
+ if (option->ctr.type[i].fields[j] == notify_field) {
+ return True;
+ }
+ }
+ }
- if (info->flags & PRINTER_MESSAGE_DRIVER)
- condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
+ DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
+ (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
+ p->dev.handlename : p->dev.printerservername,
+ notify_type, notify_field));
- result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
- printer->info_2->changeid);
+ return False;
+}
- return result;
+/* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
+
+static void notify_one_value(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
+{
+ data->notify_data.value[0] = msg->notify.value[0];
+ data->notify_data.value[1] = 0;
}
-/***********************************************************************
- Wrapper around the decision of which RPC use to in the change
- notification
- **********************************************************************/
-
-static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer,
- struct cli_state *send_cli, PRINTER_MESSAGE_INFO *msg,
- NT_PRINTER_INFO_LEVEL *info)
+static void notify_string(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
{
- WERROR result;
+ UNISTR2 unistr;
- if (valid_notify_options(Printer)) {
- /* This is a single call that can send information about multiple changes */
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
+ /* The length of the message includes the trailing \0 */
- result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
- msg, info);
- }
- else {
- /* This requires that the server send an individual event notification for each change */
- result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
- msg, info);
+ init_unistr2(&unistr, msg->notify.data, msg->len);
+
+ data->notify_data.data.length = msg->len * 2;
+ data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
+
+ if (!data->notify_data.data.string) {
+ data->notify_data.data.length = 0;
+ return;
}
- return result;
+ memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
+}
+
+static void notify_system_time(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
+{
+ SYSTEMTIME systime;
+ prs_struct ps;
+
+ if (msg->len != sizeof(time_t)) {
+ DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
+ msg->len));
+ return;
+ }
+
+ if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
+ DEBUG(5, ("notify_system_time: prs_init() failed\n"));
+ return;
+ }
+
+ if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) {
+ DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
+ return;
+ }
+
+ if (!spoolss_io_system_time("", &ps, 0, &systime))
+ return;
+
+ data->notify_data.data.length = prs_offset(&ps);
+ data->notify_data.data.string =
+ talloc(mem_ctx, prs_offset(&ps));
+
+ memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
+
+ prs_mem_free(&ps);
}
+struct notify2_message_table {
+ char *name;
+ void (*fn)(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
+};
+
+static struct notify2_message_table printer_notify_table[] = {
+ /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", NULL },
+ /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL },
+ /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL },
+ /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL },
+ /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL },
+ /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL },
+ /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL },
+ /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
+ /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL },
+ /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL },
+ /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
+ /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL },
+ /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
+ /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL },
+ /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL },
+ /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
+ /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
+ /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
+ /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
+};
+
+static struct notify2_message_table job_notify_table[] = {
+ /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
+ /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
+ /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
+ /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
+ /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
+ /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
+ /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
+ /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
+ /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
+ /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
+ /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
+ /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
+ /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
+ /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
+ /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
+ /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
+ /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
+ /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
+ /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
+ /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
+ /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
+ /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
+ /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
+ /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
+};
/***********************************************************************
Send a change notication message on all handles which have a call
back registered
**********************************************************************/
-static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
+static void process_notify2_message(struct spoolss_notify_msg *msg,
+ TALLOC_CTX *mem_ctx)
{
- Printer_entry *find_printer;
- WERROR result;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
+ Printer_entry *p;
- if (!msg) {
- DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
- return;
- }
+ for (p = printers_list; p; p = p->next) {
+ SPOOL_NOTIFY_INFO_DATA *data;
+ uint32 data_len = 1;
+ uint32 id;
- for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
+ /* Is there notification on this handle? */
- /*
- * If the entry has a connected client we send the message. There should
- * only be one of these normally when dealing with the NT/2k spooler.
- * However, iterate over all to make sure we deal with user applications
- * in addition to spooler service.
- *
- * While we are only maintaining a single connection to the client,
- * the FindFirstPrinterChangeNotification() call is made on a printer
- * handle, so "client_connected" represents the whether or not the
- * client asked for change notication on this handle.
- *
- * --jerry
- */
+ if (!p->notify.client_connected)
+ continue;
- if (find_printer->notify.client_connected==True) {
-
- /* does the client care about what changed? */
+ /* For this printer? Print servers always receive
+ notifications. */
- if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
- DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
- find_printer->client.machine));
- continue;
- }
+ if (p->printer_type == PRINTER_HANDLE_IS_PRINTER &&
+ !strequal(msg->printer, p->dev.handlename))
+ continue;
- if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
- else
- DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
+ /* Are we monitoring this event? */
- /*
- * if handle is a printer, only send if the printer_name matches.
- * ...else if handle is a printerserver, send to all
- */
+ if (!is_monitoring_event(p, msg->type, msg->field))
+ continue;
- if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
- && !strequal(msg->printer_name, find_printer->dev.handlename))
- {
- DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
- msg->printer_name, find_printer->dev.handlename ));
- continue;
+ /* OK - send the event to the client */
+
+ data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
+
+ ZERO_STRUCTP(data);
+
+ /* Convert unix jobid to smb jobid */
+
+ id = msg->id;
+
+ if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
+
+ id = sysjob_to_jobid(msg->id);
+
+ if (id == -1) {
+ DEBUG(3, ("no such unix jobid %d\n", msg->id));
+ goto done;
}
+ }
+ construct_info_data(data, msg->type, msg->field, id);
- /* lookup the printer if we have a name if we don't already have a
- valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
- will always have a non-empty msg.printer_name */
-
- if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername))
- {
-
- if (printer) {
- free_a_printer(&printer, 2);
- printer = NULL;
- }
-
- result = get_a_printer(&printer, 2, msg->printer_name);
- if (!W_ERROR_IS_OK(result))
- continue;
+ switch(msg->type) {
+ case PRINTER_NOTIFY_TYPE:
+ if (printer_notify_table[msg->field].fn)
+ printer_notify_table[msg->field].fn(
+ msg, data, mem_ctx);
+ else
+ goto done;
+ break;
+ case JOB_NOTIFY_TYPE:
+ if (job_notify_table[msg->field].fn)
+ job_notify_table[msg->field].fn(
+ msg, data, mem_ctx);
+ else
+ goto done;
+ break;
+ default:
+ DEBUG(5, ("Unknown notification type %d\n",
+ msg->type));
+ goto done;
+ }
+
+ if (!p->notify.flags)
+ cli_spoolss_rrpcn(
+ &cli, mem_ctx, &p->notify.client_hnd,
+ data_len, data, p->notify.change, 0);
+ else {
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+
+ get_a_printer(&printer, 2, msg->printer);
+
+ if (!printer) {
+ DEBUG(5, ("unable to load info2 for %s\n",
+ msg->printer));
+ goto done;
}
- /* issue the client call */
+ /* XXX: This needs to be updated for
+ PRINTER_CHANGE_SET_PRINTER_DRIVER. */
- result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
-
- if (!W_ERROR_IS_OK(result)) {
- DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
- dos_errstr(result)));
+ cli_spoolss_routerreplyprinter(
+ &cli, mem_ctx, &p->notify.client_hnd,
+ 0, printer->info_2->changeid);
+
+ free_a_printer(&printer, 2);
}
}
-}
-
+done:
return;
}
-/***************************************************************************
- Receive the notify message and decode the message. Do not send
- notification if we sent this originally as that would result in
- duplicates.
-****************************************************************************/
-static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
+/* Receive a notify2 message */
+
+static void receive_notify2_message(int msg_type, pid_t src, void *buf,
+ size_t len)
{
- PRINTER_MESSAGE_INFO msg;
-
- if (len < sizeof(msg)) {
- DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
- return;
- }
+ struct spoolss_notify_msg msg;
+ int offset = 0;
+ TALLOC_CTX *mem_ctx = talloc_init();
- memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
-
- DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
- msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
+ /* Unpack message */
- /* Iterate the printer list */
-
- send_spoolss_event_notification(&msg);
+ ZERO_STRUCT(msg);
+
+ offset += tdb_unpack((char *)buf + offset, len - offset, "f",
+ msg.printer);
+ offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
+ &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
+
+ if (msg.len == 0)
+ tdb_unpack((char *)buf + offset, len - offset, "dd",
+ &msg.notify.value[0], &msg.notify.value[1]);
+ else
+ tdb_unpack((char *)buf + offset, len - offset, "B",
+ &msg.len, &msg.notify.data);
+
+ DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
+ msg.type, msg.field, msg.flags));
+
+ if (msg.len == 0)
+ DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
+ msg.notify.value[1]));
+ else
+ dump_data(3, msg.notify.data, msg.len);
+
+ /* Process message */
+
+ process_notify2_message(&msg, mem_ctx);
+
+ /* Free message */
+
+ if (msg.len > 0)
+ free(msg.notify.data);
+
+ talloc_destroy(mem_ctx);
}
/***************************************************************************
- Send a notify event.
-****************************************************************************/
-
-static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
+ Server wrapper for cli_spoolss_routerreplyprinter() since the client
+ function can only send a single change notification at a time.
+
+ FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
+ --jerry
+ **************************************************************************/
+
+static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
+ NT_PRINTER_INFO_LEVEL *printer)
{
- char msg[sizeof(PRINTER_MESSAGE_INFO)];
- PRINTER_MESSAGE_INFO info;
+ WERROR result;
+ uint32 condition = 0x0;
- ZERO_STRUCT(info);
+ if (info->flags & PRINTER_MESSAGE_DRIVER)
+ condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
+
+ result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
+ printer->info_2->changeid);
+
+ return result;
+}
- info.low = low;
- info.high = high;
- info.flags = flags;
- fstrcpy(info.printer_name, printer_name);
+/********************************************************************
+ Send a message to ourself about new driver being installed
+ so we can upgrade the information for each printer bound to this
+ driver
+ ********************************************************************/
+
+static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
+{
+ int len = strlen(drivername);
- memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));
+ if (!len)
+ return False;
- DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
- low, high, printer_name, flags));
+ DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
+ drivername));
- message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO),
- False, NULL);
+ message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
return True;
-}
+}
+
+/**********************************************************************
+ callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
+ over all printers, upgrading ones as neessary
+ **********************************************************************/
+
+void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
+{
+ fstring drivername;
+ int snum;
+ int n_services = lp_numservices();
+
+ len = MIN(len,sizeof(drivername)-1);
+ strncpy(drivername, buf, len);
+
+ DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
+
+ /* Iterate the printer list */
+
+ for (snum=0; snum<n_services; snum++)
+ {
+ if (lp_snum_ok(snum) && lp_print_ok(snum) )
+ {
+ WERROR result;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+
+ result = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(result))
+ continue;
+
+ if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
+ {
+ DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
+
+ /* all we care about currently is the change_id */
+
+ result = mod_a_printer(*printer, 2);
+ if (!W_ERROR_IS_OK(result)) {
+ DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
+ dos_errstr(result)));
+ }
+ }
+
+ free_a_printer(&printer, 2);
+ }
+ }
+
+ /* all done */
+}
/********************************************************************
Copy routines used by convert_to_openprinterex()
@@ -924,16 +1126,6 @@ Can't find printer handle we created for printer %s\n", name ));
return WERR_INVALID_PRINTER_NAME;
}
-/*
- if (printer_default->datatype_ptr != NULL)
- {
- unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
- set_printer_hnd_datatype(handle, datatype);
- }
- else
- set_printer_hnd_datatype(handle, "");
-*/
-
/*
First case: the user is opening the print server:
@@ -997,7 +1189,7 @@ Can't find printer handle we created for printer %s\n", name ));
user_in_list(uidtoname(user.uid),
lp_printer_admin(snum)))
return WERR_OK;
-
+
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
}
@@ -1031,7 +1223,9 @@ Can't find printer handle we created for printer %s\n", name ));
printer_default->access_required = PRINTER_ACCESS_USE;
}
- if (!print_access_check(&user, snum, printer_default->access_required)) {
+ /* check smb.conf parameters and the the sec_desc */
+
+ if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) {
DEBUG(3, ("access DENIED for printer open\n"));
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
@@ -1308,10 +1502,6 @@ WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL
update_c_setprinter(False);
- if (W_ERROR_IS_OK(result)) {
- srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
- }
-
return result;
}
@@ -1344,26 +1534,17 @@ static int get_version_id (char * arch)
/********************************************************************
* _spoolss_deleteprinterdriver
- *
- * We currently delete the driver for the architecture only.
- * This can leave the driver for other archtectures. However,
- * since every printer associates a "Windows NT x86" driver name
- * and we cannot delete that one while it is in use, **and** since
- * it is impossible to assign a driver to a Samba printer without
- * having the "Windows NT x86" driver installed,...
- *
- * ....we should not get into trouble here.
- *
- * --jerry
********************************************************************/
-WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
- SPOOL_R_DELETEPRINTERDRIVER *r_u)
+WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
{
fstring driver;
fstring arch;
NT_PRINTER_DRIVER_INFO_LEVEL info;
int version;
+ struct current_user user;
+
+ get_current_user(&user, p);
unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
@@ -1373,21 +1554,89 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
/* this is what NT returns */
return WERR_INVALID_ENVIRONMENT;
}
+
+ /* if they said "Windows NT x86", then try for version 2 & 3 */
+
+ if ( version == 2 )
+ version = DRIVER_ANY_VERSION;
ZERO_STRUCT(info);
- if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
return WERR_UNKNOWN_PRINTER_DRIVER;
- }
+ if (printer_driver_in_use(info.info_3))
+ return WERR_PRINTER_DRIVER_IN_USE;
- if (printer_driver_in_use(arch, driver))
- {
+ return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
+}
+
+/********************************************************************
+ * spoolss_deleteprinterdriverex
+ ********************************************************************/
+
+WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
+{
+ fstring driver;
+ fstring arch;
+ NT_PRINTER_DRIVER_INFO_LEVEL info;
+ int version;
+ uint32 flags = q_u->delete_flags;
+ BOOL delete_files;
+ struct current_user user;
+
+ get_current_user(&user, p);
+
+ unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
+ unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
+
+ /* check that we have a valid driver name first */
+ if ((version=get_version_id(arch)) == -1) {
+ /* this is what NT returns */
+ return WERR_INVALID_ENVIRONMENT;
+ }
+
+ if ( flags & DPD_DELETE_SPECIFIC_VERSION )
+ version = q_u->version;
+ else if ( version == 2 )
+ /* if they said "Windows NT x86", then try for version 2 & 3 */
+ version = DRIVER_ANY_VERSION;
+
+ ZERO_STRUCT(info);
+
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
+ return WERR_UNKNOWN_PRINTER_DRIVER;
+
+ if ( printer_driver_in_use(info.info_3) )
return WERR_PRINTER_DRIVER_IN_USE;
+
+ /*
+ * we have a couple of cases to consider.
+ * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
+ * then the delete should fail if **any** files overlap with
+ * other drivers
+ * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
+ * non-overlapping files
+ * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
+ * is set, the do not delete any files
+ * Refer to MSDN docs on DeletePrinterDriverEx() for details.
+ */
+
+ delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
+
+ if ( delete_files )
+ {
+ /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
+
+ if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
+ /* no idea of the correct error here */
+ return WERR_ACCESS_DENIED;
}
- return delete_printer_driver(info.info_3);
+ return delete_printer_driver(info.info_3, &user, version, delete_files);
}
+
/********************************************************************
GetPrinterData on a printer server Handle.
********************************************************************/
@@ -1438,7 +1687,11 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32
*type = 0x4;
if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
return False;
+#ifndef EMULATE_WIN2K_HACK /* JERRY */
SIVAL(*data, 0, 2);
+#else
+ SIVAL(*data, 0, 3);
+#endif
*needed = 0x4;
return True;
}
@@ -1606,6 +1859,96 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
return WERR_OK;
}
+/*********************************************************
+ Connect to the client machine.
+**********************************************************/
+
+static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_machine)
+{
+ extern pstring global_myname;
+
+ ZERO_STRUCTP(the_cli);
+ if(cli_initialise(the_cli) == NULL) {
+ DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
+ return False;
+ }
+
+ if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
+ DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (ismyip(the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
+ remote_machine));
+ return False;
+ }
+
+ the_cli->protocol = PROTOCOL_NT1;
+
+ if (!cli_negprot(the_cli)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (the_cli->protocol != PROTOCOL_NT1) {
+ DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ /*
+ * Do an anonymous session setup.
+ */
+
+ if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
+ DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!(the_cli->sec_mode & 1)) {
+ DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ /*
+ * Ok - we have an anonymous connection to the IPC$ share.
+ * Now start the NT Domain stuff :-).
+ */
+
+ if(cli_nt_session_open(the_cli, PIPE_SPOOLSS) == False) {
+ DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
+ cli_nt_session_close(the_cli);
+ cli_ulogoff(the_cli);
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ return True;
+}
+
/***************************************************************************
Connect to the client.
****************************************************************************/
@@ -1626,15 +1969,14 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin
if(!spoolss_connect_to_client(&cli, unix_printer))
return False;
- message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
-
+ message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
}
smb_connections++;
result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
type, handle);
-
+
if (!W_ERROR_IS_OK(result))
DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
dos_errstr(result)));
@@ -1646,9 +1988,8 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin
* _spoolss_rffpcnex
* ReplyFindFirstPrinterChangeNotifyEx
*
- * jfmxxxx: before replying OK: status=0
- * should do a rpc call to the workstation asking ReplyOpenPrinter
- * have to code it, later.
+ * before replying OK: status=0 a rpc call is made to the workstation
+ * asking ReplyOpenPrinter
*
* in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
* called from api_spoolss_rffpcnex
@@ -1681,15 +2022,17 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE
Printer->notify.option=dup_spool_notify_option(option);
- unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
+ unistr2_to_ascii(Printer->notify.localmachine, localmachine,
+ sizeof(Printer->notify.localmachine)-1);
+
+ /* Connect to the client machine and send a ReplyOpenPrinter */
- /* connect to the client machine and send a ReplyOpenPrinter */
- if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
+ if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine,
Printer->notify.printerlocal, 1,
&Printer->notify.client_hnd))
- {
- Printer->notify.client_connected=True;
- }
+ return WERR_SERVER_UNAVAILABLE;
+
+ Printer->notify.client_connected=True;
return WERR_OK;
}
@@ -1711,7 +2054,7 @@ void spoolss_notify_server_name(int snum,
len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1746,7 +2089,7 @@ void spoolss_notify_printer_name(int snum,
len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1772,7 +2115,7 @@ void spoolss_notify_share_name(int snum,
len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1800,7 +2143,7 @@ void spoolss_notify_port_name(int snum,
len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1826,7 +2169,8 @@ void spoolss_notify_driver_name(int snum,
uint32 len;
len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1855,7 +2199,7 @@ void spoolss_notify_comment(int snum,
else
len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1882,7 +2226,7 @@ void spoolss_notify_location(int snum,
len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1921,7 +2265,7 @@ void spoolss_notify_sepfile(int snum,
len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1948,7 +2292,7 @@ void spoolss_notify_print_processor(int snum,
len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -1975,7 +2319,7 @@ void spoolss_notify_parameters(int snum,
len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -2002,7 +2346,7 @@ void spoolss_notify_datatype(int snum,
len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -2162,7 +2506,7 @@ static void spoolss_notify_username(int snum,
len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -2202,7 +2546,7 @@ static void spoolss_notify_job_name(int snum,
len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -2252,7 +2596,7 @@ static void spoolss_notify_job_status_string(int snum,
len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
@@ -2376,8 +2720,6 @@ static void spoolss_notify_submitted_time(int snum,
SSVAL(p, 14, st.milliseconds);
}
-#define END 65535
-
struct s_notify_info_data_table
{
uint16 type;
@@ -2389,59 +2731,61 @@ struct s_notify_info_data_table
NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
};
+/* A table describing the various print notification constants and
+ whether the notification data is a pointer to a variable sized
+ buffer, a one value uint32 or a two value uint32. */
+
struct s_notify_info_data_table notify_info_data_table[] =
{
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, spoolss_notify_total_pages },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, spoolss_notify_pages_printed },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
-{ END, END, "", END, NULL }
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, spoolss_notify_security_desc },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
};
/*******************************************************************
@@ -2452,43 +2796,46 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field)
{
int i=0;
- while (notify_info_data_table[i].type != END)
- {
- if ( (notify_info_data_table[i].type == type ) &&
- (notify_info_data_table[i].field == field ) )
- {
- return (notify_info_data_table[i].size);
+ for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ if (notify_info_data_table[i].type == type &&
+ notify_info_data_table[i].field == field) {
+ switch(notify_info_data_table[i].size) {
+ case NOTIFY_ONE_VALUE:
+ case NOTIFY_TWO_VALUE:
+ return 1;
+ case NOTIFY_STRING:
+ return 2;
+
+ /* The only pointer notify data I have seen on
+ the wire is the submitted time and this has
+ the notify size set to 4. -tpot */
+
+ case NOTIFY_POINTER:
+ return 4;
+ }
}
- i++;
}
- return (65535);
+
+ DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
+
+ return 0;
}
/*******************************************************************
Return the type of notify_info_data.
********************************************************************/
-static BOOL type_of_notify_info_data(uint16 type, uint16 field)
+static int type_of_notify_info_data(uint16 type, uint16 field)
{
int i=0;
- while (notify_info_data_table[i].type != END)
- {
- if ( (notify_info_data_table[i].type == type ) &&
- (notify_info_data_table[i].field == field ) )
- {
- if (notify_info_data_table[i].size == POINTER)
- {
- return (False);
- }
- else
- {
- return (True);
- }
- }
- i++;
+ for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ if (notify_info_data_table[i].type == type &&
+ notify_info_data_table[i].field == field)
+ return notify_info_data_table[i].size;
}
- return (False);
+
+ return False;
}
/****************************************************************************
@@ -2496,21 +2843,18 @@ static BOOL type_of_notify_info_data(uint16 type, uint16 field)
static int search_notify(uint16 type, uint16 field, int *value)
{
- int j;
- BOOL found;
+ int i;
- for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
- {
- if ( (notify_info_data_table[j].type == type ) &&
- (notify_info_data_table[j].field == field ) )
- found=True;
+ for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ if (notify_info_data_table[i].type == type &&
+ notify_info_data_table[i].field == field &&
+ notify_info_data_table[i].fn != NULL) {
+ *value = i;
+ return True;
+ }
}
- *value=--j;
-
- if ( found && (notify_info_data_table[j].fn != NULL) )
- return True;
- else
- return False;
+
+ return False;
}
/****************************************************************************
@@ -2521,7 +2865,12 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16
info_data->type = type;
info_data->field = field;
info_data->reserved = 0;
- info_data->id = id;
+
+ if (type == JOB_NOTIFY_TYPE)
+ info_data->id = id;
+ else
+ info_data->id = 0;
+
info_data->size = size_of_notify_info_data(type, field);
info_data->enc_type = type_of_notify_info_data(type, field);
}
@@ -2570,7 +2919,7 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int
current_data=&info->data[info->count];
- construct_info_data(current_data, type, field, id);
+ construct_info_data(current_data, type, field, id);
DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
notify_info_data_table[j].name, snum, printer->info_2->printername ));
@@ -2812,7 +3161,6 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY
WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 change = q_u->change; - notused. */
/* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
SPOOL_NOTIFY_INFO *info = &r_u->info;
@@ -2830,17 +3178,19 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN
DEBUG(4,("Printer type %x\n",Printer->printer_type));
- /* jfm: the change value isn't used right now.
- * we will honour it when
- * a) we'll be able to send notification to the client
- * b) we'll have a way to communicate between the spoolss process.
- *
- * same thing for option->flags
+ /*
+ * We are now using the change value, and
* I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
* I don't have a global notification system, I'm sending back all the
* informations even when _NOTHING_ has changed.
*/
+ /* We need to keep track of the change value to send back in
+ RRPCN replies otherwise our updates are ignored. */
+
+ if (Printer->notify.client_connected)
+ Printer->notify.change = q_u->change;
+
/* just ignore the SPOOL_NOTIFY_OPTION */
switch (Printer->printer_type) {
@@ -2932,7 +3282,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
printer->global_counter = global_counter;
printer->total_pages = 0;
-#if 0 /* JERRY */
+#ifndef EMULATE_WIN2K_HACK /* JERRY */
printer->major_version = 0x0004; /* NT 4 */
printer->build_version = 0x0565; /* build 1381 */
#else
@@ -2971,7 +3321,6 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum)
* construct_printer_info_1
* fill a printer_info_1 struct
********************************************************************/
-
static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
{
pstring chaine;
@@ -3046,8 +3395,10 @@ static DEVICEMODE *construct_dev_mode(int snum)
if (printer->info_2->devmode)
ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
- if (ntdevmode == NULL)
+ if (ntdevmode == NULL) {
+ DEBUG(5, ("BONG! There was no device mode!\n"));
goto fail;
+ }
DEBUGADD(8,("loading DEVICEMODE\n"));
@@ -3408,10 +3759,26 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer,
enum_all_printers_info_1_network.
*********************************************************************/
-static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
+static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
+ char *s = name;
+
DEBUG(4,("enum_all_printers_info_1_network\n"));
+ /* If we respond to a enum_printers level 1 on our name with flags
+ set to PRINTER_ENUM_REMOTE with a list of printers then these
+ printers incorrectly appear in the APW browse list.
+ Specifically the printers for the server appear at the workgroup
+ level where all the other servers in the domain are
+ listed. Windows responds to this call with a
+ WERR_CAN_NOT_COMPLETE so we should do the same. */
+
+ if (name[0] == '\\' && name[1] == '\\')
+ s = name + 2;
+
+ if (is_myname_or_ipaddr(s))
+ return WERR_CAN_NOT_COMPLETE;
+
return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
}
@@ -3449,9 +3816,9 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3
}
/* check the required size. */
- for (i=0; i<*returned; i++)
+ for (i=0; i<*returned; i++)
(*needed) += spoolss_size_printer_info_2(&printers[i]);
-
+
if (!alloc_buffer_size(buffer, *needed)) {
for (i=0; i<*returned; i++) {
free_devmode(printers[i].devmode);
@@ -3498,7 +3865,7 @@ static WERROR enumprinters_level1( uint32 flags, fstring name,
return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
if (flags & PRINTER_ENUM_NETWORK)
- return enum_all_printers_info_1_network(buffer, offered, needed, returned);
+ return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
return WERR_OK; /* NT4sp5 does that */
}
@@ -3681,7 +4048,7 @@ static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, u
/* check the required size. */
*needed += spoolss_size_printer_info_2(printer);
-
+
if (!alloc_buffer_size(buffer, *needed)) {
free_printer_info_2(printer);
return WERR_INSUFFICIENT_BUFFER;
@@ -4728,6 +5095,7 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
{
+ extern userdom_struct current_user_info;
char *cmd = lp_addprinter_cmd();
char **qlines;
pstring command;
@@ -4742,13 +5110,13 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
get_called_name());
/* change \ to \\ for the shell */
all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
-
+ standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
+
slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
cmd, printer->info_2->printername, printer->info_2->sharename,
printer->info_2->portname, printer->info_2->drivername,
printer->info_2->location, driverlocation, remote_machine);
- /* Convert script args to unix-codepage */
DEBUG(10,("Running [%s]\n", command));
ret = smbrun(command, &fd);
DEBUGADD(10,("returned [%d]\n", ret));
@@ -5039,13 +5407,10 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
int snum;
NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
- PRINTER_MESSAGE_INFO msg;
WERROR result;
DEBUG(8,("update_printer\n"));
-
- ZERO_STRUCT(msg);
-
+
result = WERR_OK;
if (level!=2) {
@@ -5159,8 +5524,11 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
* bound to the printer, simulating what happens in the Windows arch.
*/
if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
- set_driver_init(printer, 2);
- msg.flags |= PRINTER_MESSAGE_DRIVER;
+ if (!set_driver_init(printer, 2)) {
+ DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
+ printer->info_2->drivername));
+ }
+ notify_printer_driver(snum, printer->info_2->drivername);
}
}
@@ -5171,28 +5539,18 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
all the possible changes */
if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
- msg.flags |= PRINTER_MESSAGE_COMMENT;
+ notify_printer_comment(snum, printer->info_2->comment);
if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
- msg.flags |= PRINTER_MESSAGE_SHARENAME;
+ notify_printer_sharename(snum, printer->info_2->sharename);
if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
- msg.flags |= PRINTER_MESSAGE_PORT;
+ notify_printer_port(snum, printer->info_2->portname);
if (!strequal(printer->info_2->location, old_printer->info_2->location))
- msg.flags |= PRINTER_MESSAGE_LOCATION;
-
- ZERO_STRUCT(msg);
-
- msg.low = PRINTER_CHANGE_ADD_PRINTER;
- fstrcpy(msg.printer_name, printer->info_2->printername);
-
- /* only send a notify if something changed */
- if (msg.flags) {
- srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
- }
+ notify_printer_location(snum, printer->info_2->location);
- done:
+done:
free_a_printer(&printer, 2);
free_a_printer(&old_printer, 2);
@@ -5310,7 +5668,7 @@ static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
int position, int snum,
- NT_PRINTER_INFO_LEVEL *ntprinter,
+ NT_PRINTER_INFO_LEVEL *ntprinter,
DEVICEMODE *devmode)
{
pstring temp_name;
@@ -5427,7 +5785,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
*returned = 0;
goto done;
}
-
+
if (!(devmode = construct_dev_mode(snum))) {
*returned = 0;
result = WERR_NOMEM;
@@ -5470,6 +5828,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
SAFE_FREE(info);
return result;
+
}
/****************************************************************************
@@ -5538,8 +5897,6 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
{
POLICY_HND *handle = &q_u->handle;
uint32 jobid = q_u->jobid;
-/* uint32 level = q_u->level; - notused. */
-/* JOB_INFO *ctr = &q_u->ctr; - notused. */
uint32 command = q_u->command;
struct current_user user;
@@ -5597,9 +5954,7 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
@@ -5678,9 +6033,7 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
@@ -5760,9 +6113,7 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
@@ -6415,9 +6766,6 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
}
update_c_setprinter(False);
-
- srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
-
free_a_printer(&printer,2);
return WERR_OK;
@@ -6462,10 +6810,12 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
WERROR err = WERR_OK;
NT_PRINTER_DRIVER_INFO_LEVEL driver;
struct current_user user;
-
+ fstring driver_name;
+ uint32 version;
+
ZERO_STRUCT(driver);
- get_current_user(&user, p);
+ get_current_user(&user, p);
if (!convert_printer_driver_info(info, &driver, level)) {
err = WERR_NOMEM;
@@ -6489,11 +6839,131 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
goto done;
}
- done:
+ /* BEGIN_ADMIN_LOG */
+ switch(level) {
+ case 3:
+ sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
+ driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
+ fstrcpy(driver_name, driver.info_3->name);
+ break;
+ case 6:
+ sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
+ driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
+ fstrcpy(driver_name, driver.info_6->name);
+ break;
+ }
+ /* END_ADMIN_LOG */
+
+ /*
+ * I think this is where he DrvUpgradePrinter() hook would be
+ * be called in a driver's interface DLL on a Windows NT 4.0/2k
+ * server. Right now, we just need to send ourselves a message
+ * to update each printer bound to this driver. --jerry
+ */
+
+ if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
+ DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
+ driver_name));
+ }
+
+ /*
+ * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
+ * decide if the driver init data should be deleted. The rules are:
+ * 1) never delete init data if it is a 9x driver, they don't use it anyway
+ * 2) delete init data only if there is no 2k/Xp driver
+ * 3) always delete init data
+ * The generalized rule is always use init data from the highest order driver.
+ * It is necessary to follow the driver install by an initialization step to
+ * finish off this process.
+ */
+ if (level == 3)
+ version = driver.info_3->cversion;
+ else if (level == 6)
+ version = driver.info_6->version;
+ else
+ version = -1;
+ switch (version) {
+ /*
+ * 9x printer driver - never delete init data
+ */
+ case 0:
+ DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
+ driver_name));
+ break;
+
+ /*
+ * Nt or 2k (compatiblity mode) printer driver - only delete init data if
+ * there is no 2k/Xp driver init data for this driver name.
+ */
+ case 2:
+ {
+ NT_PRINTER_DRIVER_INFO_LEVEL driver1;
+
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
+ /*
+ * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
+ */
+ if (!del_driver_init(driver_name))
+ DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
+ } else {
+ /*
+ * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
+ */
+ free_a_printer_driver(driver1,3);
+ DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
+ driver_name));
+ }
+ }
+ break;
+
+ /*
+ * 2k or Xp printer driver - always delete init data
+ */
+ case 3:
+ if (!del_driver_init(driver_name))
+ DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
+ break;
+
+ default:
+ DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
+ break;
+ }
+
+
+done:
free_a_printer_driver(driver, level);
return err;
}
+/********************************************************************
+ * spoolss_addprinterdriverex
+ ********************************************************************/
+
+WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
+{
+ SPOOL_Q_ADDPRINTERDRIVER q_u_local;
+ SPOOL_R_ADDPRINTERDRIVER r_u_local;
+
+ /*
+ * we only support the semantics of AddPrinterDriver()
+ * i.e. only copy files that are newer than existing ones
+ */
+
+ if ( q_u->copy_flags != APD_COPY_NEW_FILES )
+ return WERR_ACCESS_DENIED;
+
+ /* just pass the information off to _spoolss_addprinterdriver() */
+ ZERO_STRUCT(q_u_local);
+ ZERO_STRUCT(r_u_local);
+
+ q_u_local.server_name_ptr = q_u->server_name_ptr;
+ copy_unistr2(&q_u_local.server_name, &q_u->server_name);
+ q_u_local.level = q_u->level;
+ memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
+
+ return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
+}
+
/****************************************************************************
****************************************************************************/
@@ -6632,23 +7102,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
if ( (in_value_len==0) && (in_data_len==0) ) {
DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
-#if 0
- /*
- * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
- * if this parameter size doesn't exist.
- * Ok - my opinion here is that the client is not asking for the greatest
- * possible size of all the parameters, but is asking specifically for the size needed
- * for this specific parameter. In that case we can remove the loop below and
- * simplify this lookup code considerably. JF - comments welcome. JRA.
- */
-
- if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
- SAFE_FREE(data);
- free_a_printer(&printer, 2);
- return WERR_NO_MORE_ITEMS;
- }
-#endif
-
SAFE_FREE(data);
param_index=0;
@@ -6692,7 +7145,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
return WERR_NOMEM;
- *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
/* the data is counted in bytes */
*out_max_data_len = in_data_len;
@@ -6720,7 +7173,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
return WERR_NOMEM;
}
- *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0);
*out_type=type;
@@ -6747,10 +7200,8 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
POLICY_HND *handle = &q_u->handle;
UNISTR2 *value = &q_u->value;
uint32 type = q_u->type;
-/* uint32 max_len = q_u->max_len; - notused. */
uint8 *data = q_u->data;
uint32 real_len = q_u->real_len;
-/* uint32 numeric_data = q_u->numeric_data; - notused. */
NT_PRINTER_INFO_LEVEL *printer = NULL;
NT_PRINTER_PARAM *param = NULL, old_param;
@@ -7022,8 +7473,6 @@ done:
WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* UNISTR2 *uni_name = &q_u->name; - notused. */
-/* uint32 level = q_u->level; - notused. */
FORM *form = &q_u->form;
nt_forms_struct tmpForm;
int snum;
@@ -7114,12 +7563,10 @@ static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, ui
WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
-/* UNISTR2 *environment = &q_u->environment; - notused. */
uint32 level = q_u->level;
- NEW_BUFFER *buffer = NULL;
+ NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
- uint32 *needed = &r_u->needed;
+ uint32 *needed = &r_u->needed;
uint32 *returned = &r_u->returned;
/* that's an [in out] buffer */
@@ -7183,8 +7630,6 @@ static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered,
WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
-/* UNISTR2 *processor = &q_u->processor; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
@@ -7279,11 +7724,10 @@ static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint
WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
uint32 level = q_u->level;
- NEW_BUFFER *buffer = NULL;
+ NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
- uint32 *needed = &r_u->needed;
+ uint32 *needed = &r_u->needed;
uint32 *returned = &r_u->returned;
/* that's an [in out] buffer */
@@ -7427,7 +7871,7 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
free_job_info_2(info_2); /* Also frees devmode */
SAFE_FREE(info_2);
free_a_printer(&ntprinter, 2);
-
+
return ret;
}
@@ -7594,6 +8038,34 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
}
+
+/********************************************************************
+ * spoolss_deleteprinterdataex
+ ********************************************************************/
+
+WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
+{
+ SPOOL_Q_DELETEPRINTERDATA q_u_local;
+ SPOOL_R_DELETEPRINTERDATA r_u_local;
+ fstring key;
+
+ /* From MSDN documentation of SetPrinterDataEx: pass request to
+ SetPrinterData if key is "PrinterDriverData" */
+
+ unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+
+ if (strcmp(key, "PrinterDriverData") != 0)
+ return WERR_INVALID_PARAM;
+
+ memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
+ copy_unistr2(&q_u_local.valuename, &q_u->valuename);
+
+ return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
+}
+
+
+
+
/********************************************************************
* spoolss_enumprinterkey
********************************************************************/
@@ -7661,6 +8133,34 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO
}
/********************************************************************
+ * spoolss_deleteprinterkey
+ ********************************************************************/
+
+WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
+{
+ Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
+ fstring key;
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
+ return WERR_BADFID;
+ }
+
+ unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+
+ if (strcmp(key, "PrinterDriverData") != 0)
+ return WERR_INVALID_PARAM;
+
+ /*
+ * this is what 2k returns when you try to delete the "PrinterDriverData"
+ * key
+ */
+
+ return WERR_ACCESS_DENIED;
+}
+
+
+/********************************************************************
* spoolss_enumprinterdataex
********************************************************************/
@@ -7801,7 +8301,7 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
- if (get_short_archi(short_archi, long_archi)==FALSE)
+ if (get_short_archi(short_archi, long_archi)==False)
return WERR_INVALID_ENVIRONMENT;
if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL)
@@ -7834,6 +8334,7 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
uint32 *needed = &r_u->needed;
+ WERROR result;
/* that's an [in out] buffer */
spoolss_move_buffer(q_u->buffer, &r_u->buffer);
@@ -7845,12 +8346,13 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
switch(level) {
case 1:
- return getprintprocessordirectory_level_1
+ result = getprintprocessordirectory_level_1
(&q_u->name, &q_u->environment, buffer, offered, needed);
default:
- return WERR_UNKNOWN_LEVEL;
+ result = WERR_UNKNOWN_LEVEL;
}
- return WERR_ACCESS_DENIED;
+ return result;
}
+
diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c
index ee4ec8aa0a..5e1c005d54 100644
--- a/source3/rpc_server/srv_srvsvc.c
+++ b/source3/rpc_server/srv_srvsvc.c
@@ -25,6 +25,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/*******************************************************************
api_srv_net_srv_get_info
********************************************************************/
@@ -492,25 +495,25 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
\PIPE\srvsvc commands
********************************************************************/
-struct api_struct api_srv_cmds[] =
+static const struct api_struct api_srv_cmds[] =
{
- { "SRV_NETCONNENUM" , SRV_NETCONNENUM , api_srv_net_conn_enum },
- { "SRV_NETSESSENUM" , SRV_NETSESSENUM , api_srv_net_sess_enum },
- { "SRV_NETSHAREENUM_ALL" , SRV_NETSHAREENUM_ALL , api_srv_net_share_enum_all },
- { "SRV_NETSHAREENUM" , SRV_NETSHAREENUM , 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_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_NETFILEENUM" , SRV_NETFILEENUM , 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_NETFILEQUERYSECDESC",SRV_NETFILEQUERYSECDESC,api_srv_net_file_query_secdesc},
- { "SRV_NETFILESETSECDESC" , SRV_NETFILESETSECDESC , api_srv_net_file_set_secdesc},
- { NULL , 0 , NULL }
+ { "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_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},
+ { NULL , 0 , NULL }
};
/*******************************************************************
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 1f3b1945e3..b5f6bd2f07 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -23,6 +23,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
/*******************************************************************
@@ -38,7 +41,7 @@ static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int sn
pstrcpy(net_name, lp_servicename(snum));
pstrcpy(remark, lp_comment(snum));
- standard_sub_conn(p->conn, remark);
+ standard_sub_conn(p->conn, remark,sizeof(remark));
len_net_name = strlen(net_name);
/* work out the share type */
@@ -70,7 +73,7 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
pstrcpy(net_name, lp_servicename(snum));
pstrcpy(remark, lp_comment(snum));
- standard_sub_conn(p->conn, remark);
+ standard_sub_conn(p->conn, remark,sizeof(remark));
pstrcpy(path, "C:");
pstrcat(path, lp_pathname(snum));
@@ -308,7 +311,7 @@ void map_generic_share_sd_bits(SEC_DESC *psd)
Can this user access with share with the required permissions ?
********************************************************************/
-BOOL share_access_check(connection_struct *conn, int snum, uint16 vuid, uint32 desired_access)
+BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, uint32 desired_access)
{
uint32 granted;
NTSTATUS status;
@@ -316,7 +319,6 @@ BOOL share_access_check(connection_struct *conn, int snum, uint16 vuid, uint32 d
SEC_DESC *psd = NULL;
size_t sd_size;
NT_USER_TOKEN *token = NULL;
- user_struct *vuser = get_valid_user_struct(vuid);
BOOL ret = True;
mem_ctx = talloc_init();
@@ -355,7 +357,7 @@ static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501,
pstrcpy(net_name, lp_servicename(snum));
pstrcpy(remark, lp_comment(snum));
- standard_sub_conn(p->conn, remark);
+ standard_sub_conn(p->conn, remark, sizeof(remark));
len_net_name = strlen(net_name);
@@ -394,7 +396,7 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
pstrcpy(net_name, lp_servicename(snum));
pstrcpy(remark, lp_comment(snum));
- standard_sub_conn(p->conn, remark);
+ standard_sub_conn(p->conn, remark,sizeof(remark));
pstrcpy(path, "C:");
pstrcat(path, lp_pathname(snum));
@@ -638,11 +640,13 @@ static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *
static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot)
{
+ struct sessionid *session_list;
uint32 num_entries = 0;
- (*stot) = 1;
+ (*stot) = list_sessions(&session_list);
if (ss0 == NULL) {
(*snum) = 0;
+ SAFE_FREE(session_list);
return;
}
@@ -651,7 +655,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
if (snum) {
for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
init_srv_sess_0_info(&ss0->info_0[num_entries],
- &ss0->info_0_str[num_entries], "MACHINE");
+ &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine);
/* move on to creating next session */
/* move on to creating next sess */
@@ -671,6 +675,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
ss0->ptr_sess_info = 0;
ss0->num_entries_read2 = 0;
}
+ SAFE_FREE(session_list);
}
/*******************************************************************
@@ -693,11 +698,13 @@ static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1,
static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot)
{
+ struct sessionid *session_list;
uint32 num_entries = 0;
- (*stot) = 1;
+ (*stot) = list_sessions(&session_list);
if (ss1 == NULL) {
(*snum) = 0;
+ SAFE_FREE(session_list);
return;
}
@@ -706,8 +713,10 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto
if (snum) {
for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
init_srv_sess_1_info(&ss1->info_1[num_entries],
- &ss1->info_1_str[num_entries],
- "MACHINE", "dummy_user", 1, 10, 5, 0);
+ &ss1->info_1_str[num_entries],
+ session_list[*snum].remote_machine,
+ session_list[*snum].username,
+ 1, 10, 5, 0);
/* move on to creating next session */
/* move on to creating next sess */
@@ -942,73 +951,45 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
}
/*******************************************************************
- fill in a file info level 3 structure.
- ********************************************************************/
-
-static void init_srv_file_3_info(FILE_INFO_3 *fl3, FILE_INFO_3_STR *str3,
- uint32 fnum, uint32 perms, uint32 num_locks,
- char *path_name, char *user_name)
-{
- init_srv_file_info3(fl3 , fnum, perms, num_locks, path_name, user_name);
- init_srv_file_info3_str(str3, path_name, user_name);
-}
-
-/*******************************************************************
- fill in a file info level 3 structure.
- ********************************************************************/
-
-static void init_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot)
-{
- uint32 num_entries = 0;
- (*ftot) = 1;
-
- if (fl3 == NULL) {
- (*fnum) = 0;
- return;
- }
-
- DEBUG(5,("init_srv_file_3_fl3\n"));
-
- for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++) {
- init_srv_file_3_info(&fl3->info_3[num_entries],
- &fl3->info_3_str[num_entries],
- (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user");
-
- /* move on to creating next file */
- num_entries++;
- }
-
- fl3->num_entries_read = num_entries;
- fl3->ptr_file_info = num_entries > 0 ? 1 : 0;
- fl3->num_entries_read2 = num_entries;
-
- if ((*fnum) >= (*ftot)) {
- (*fnum) = 0;
- }
-}
-
-/*******************************************************************
makes a SRV_R_NET_FILE_ENUM structure.
********************************************************************/
-static WERROR init_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr,
+static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
int switch_value, uint32 *resume_hnd, uint32 *total_entries)
{
WERROR status = WERR_OK;
+ TALLOC_CTX *ctx = p->mem_ctx;
DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
+ *total_entries = 1; /* dummy entries only, for */
ctr->switch_value = switch_value;
+ ctr->num_entries = *total_entries - *resume_hnd;
+ if (ctr->num_entries < 0)
+ ctr->num_entries = 0;
+ ctr->num_entries2 = ctr->num_entries;
switch (switch_value) {
- case 3:
- init_srv_file_info_3(&ctr->file.info3, resume_hnd, total_entries);
- ctr->ptr_file_ctr = 1;
+ case 3: {
+ int i;
+ if (*total_entries > 0) {
+ ctr->ptr_entries = 1;
+ ctr->file.info3 = talloc(ctx, ctr->num_entries *
+ sizeof(SRV_FILE_INFO_3));
+ }
+ for (i=0 ;i<ctr->num_entries;i++) {
+ init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user");
+ init_srv_file_info3_str(&ctr->file.info3[i].info_3_str, "\\PIPE\\samr", "dummy user");
+
+ }
+ ctr->ptr_file_info = 1;
+ *resume_hnd = 0;
break;
+ }
default:
DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value));
(*resume_hnd = 0);
(*total_entries) = 0;
- ctr->ptr_file_ctr = 0;
+ ctr->ptr_entries = 0;
status = WERR_UNKNOWN_LEVEL;
break;
}
@@ -1020,7 +1001,7 @@ static WERROR init_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr,
makes a SRV_R_NET_FILE_ENUM structure.
********************************************************************/
-static void init_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n,
+static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n,
uint32 resume_hnd, int file_level, int switch_value)
{
DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
@@ -1029,7 +1010,7 @@ static void init_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n,
if (file_level == 0)
r_n->status = WERR_UNKNOWN_LEVEL;
else
- r_n->status = init_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
+ r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
if (!W_ERROR_IS_OK(r_n->status))
resume_hnd = 0;
@@ -1053,11 +1034,21 @@ WERROR _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R
DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to srv_net_srv_get_info\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
switch (q_u->switch_value) {
+
+ /* Technically level 102 should only be available to
+ Administrators but there isn't anything super-secret
+ here, as most of it is made up. */
+
case 102:
init_srv_info_102(&ctr->srv.sv102,
500, global_myname,
- string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
+ string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
lp_major_announce_version(), lp_minor_announce_version(),
lp_default_server_announce(),
0xffffffff, /* users */
@@ -1116,19 +1107,13 @@ net file enum
WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
{
- r_u->ctr = (SRV_FILE_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_FILE_INFO_CTR));
- if (!r_u->ctr)
- return WERR_NOMEM;
-
- ZERO_STRUCTP(r_u->ctr);
-
DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
/* set up the */
- init_srv_r_net_file_enum(r_u,
+ init_srv_r_net_file_enum(p, r_u,
get_enum_hnd(&q_u->enum_hnd),
q_u->file_level,
- q_u->ctr->switch_value);
+ q_u->ctr.switch_value);
DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
@@ -1193,6 +1178,11 @@ WERROR _srv_net_share_enum_all(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R
{
DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to srv_net_share_enum_all\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
/* Create the list of shares for the response. */
init_srv_r_net_share_enum(p, r_u,
q_u->ctr.info_level,
@@ -1211,6 +1201,11 @@ WERROR _srv_net_share_enum(pipes_struct *p, SRV_Q_NET_SHARE_ENUM *q_u, SRV_R_NET
{
DEBUG(5,("_srv_net_share_enum: %d\n", __LINE__));
+ if (!pipe_access_check(p)) {
+ DEBUG(3, ("access denied to srv_net_share_enum\n"));
+ return WERR_ACCESS_DENIED;
+ }
+
/* Create the list of shares for the response. */
init_srv_r_net_share_enum(p, r_u,
q_u->ctr.info_level,
@@ -1829,7 +1824,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
"Nigel Williams" <nigel@veritas.com>.
***********************************************************************************/
-const char *server_disks[] = {"C:"};
+static const char *server_disks[] = {"C:"};
static uint32 get_server_disk_count(void)
{
diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c
index 53bbebb95e..f896d1d9d8 100644
--- a/source3/rpc_server/srv_util.c
+++ b/source3/rpc_server/srv_util.c
@@ -38,6 +38,9 @@
#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.
@@ -93,6 +96,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
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.
@@ -108,17 +112,15 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
*prids=NULL;
*numgroups=0;
- lp_winbind_gid(&winbind_gid_low, &winbind_gid_high);
+ 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)));
- sid_peek_rid(q_sid, &rid);
-
pdb_init_sam(&sam_pass);
become_root();
- ret = pdb_getsampwrid(sam_pass, rid);
+ ret = pdb_getsampwsid(sam_pass, q_sid);
unbecome_root();
if (ret == False) {
pdb_free_sam(&sam_pass);
@@ -157,7 +159,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
}
/* Don't return winbind groups as they are not local! */
- if ((grp->gr_gid >= winbind_gid_low) && (grp->gr_gid <= winbind_gid_high)) {
+ if (winbind_groups_exist && (grp->gr_gid >= winbind_gid_low) && (grp->gr_gid <= winbind_gid_high)) {
DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map.nt_name));
continue;
}
@@ -226,7 +228,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
}
/* Don't return winbind groups as they are not local! */
- if ((gid >= winbind_gid_low) && (gid <= winbind_gid_high)) {
+ 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;
}
@@ -404,6 +406,8 @@ NTSTATUS local_lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
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.
********************************************************************/
@@ -448,6 +452,8 @@ NTSTATUS local_lookup_user_name(uint32 rid, char *user_name, uint32 *type)
return NT_STATUS_NONE_MAPPED;
}
+#endif
+
/*******************************************************************
Look up a local (domain) group name and return a rid
********************************************************************/
diff --git a/source3/rpc_server/srv_wkssvc.c b/source3/rpc_server/srv_wkssvc.c
index 8eb5b3002e..c783becbbe 100644
--- a/source3/rpc_server/srv_wkssvc.c
+++ b/source3/rpc_server/srv_wkssvc.c
@@ -24,6 +24,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
/*******************************************************************
api_wks_query_info
********************************************************************/
@@ -55,7 +58,7 @@ static BOOL api_wks_query_info(pipes_struct *p)
/*******************************************************************
\PIPE\wkssvc commands
********************************************************************/
-struct api_struct api_wks_cmds[] =
+static struct api_struct api_wks_cmds[] =
{
{ "WKS_Q_QUERY_INFO", WKS_QUERY_INFO, api_wks_query_info },
{ NULL , 0 , NULL }
diff --git a/source3/rpc_server/srv_wkssvc_nt.c b/source3/rpc_server/srv_wkssvc_nt.c
index 637c95af69..7687e7b00a 100644
--- a/source3/rpc_server/srv_wkssvc_nt.c
+++ b/source3/rpc_server/srv_wkssvc_nt.c
@@ -25,6 +25,9 @@
#include "includes.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
/*******************************************************************