From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/rpc_server/srv_dfs_nt.c | 10 +- source3/rpc_server/srv_lsa_nt.c | 31 +-- source3/rpc_server/srv_pipe.c | 105 +++---- source3/rpc_server/srv_pipe_hnd.c | 9 +- source3/rpc_server/srv_samr_nt.c | 17 +- source3/rpc_server/srv_samr_util.c | 35 ++- source3/rpc_server/srv_spoolss_nt.c | 98 +++---- source3/rpc_server/srv_srvsvc.c | 33 ++- source3/rpc_server/srv_srvsvc_nt.c | 520 +++++++++++++++++++++++------------ source3/rpc_server/srv_svcctl_nt.c | 2 +- source3/rpc_server/srv_unixinfo.c | 163 +++++++++++ source3/rpc_server/srv_unixinfo_nt.c | 166 +++++++++++ 12 files changed, 856 insertions(+), 333 deletions(-) create mode 100644 source3/rpc_server/srv_unixinfo.c create mode 100644 source3/rpc_server/srv_unixinfo_nt.c (limited to 'source3/rpc_server') diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index 8239584522..c7f8e05d91 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -40,7 +40,6 @@ uint32 _dfs_GetManagerVersion(pipes_struct *p, NETDFS_Q_DFS_GETMANAGERVERSION *q WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) { - struct current_user user; struct junction_map jn; struct referral* old_referral_list = NULL; BOOL exists = False; @@ -48,9 +47,7 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) pstring dfspath, servername, sharename; pstring altpath; - get_current_user(&user,p); - - if (user.ut.uid != 0) { + if (p->pipe_user.ut.uid != 0) { DEBUG(10,("_dfs_add: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } @@ -104,16 +101,13 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u, NETDFS_R_DFS_REMOVE *r_u) { - struct current_user user; struct junction_map jn; BOOL found = False; pstring dfspath, servername, sharename; pstring altpath; - get_current_user(&user,p); - - if (user.ut.uid != 0) { + if (p->pipe_user.ut.uid != 0) { DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index efa7156eea..2cc5ef6110 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -1557,17 +1557,23 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR * I don't know if it's the right one. not documented. * but guessed with rpcclient. */ - if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION)) + if (!(handle->access & POLICY_GET_PRIVATE_INFORMATION)) { + DEBUG(10, ("_lsa_create_account: No POLICY_GET_PRIVATE_INFORMATION access right!\n")); return NT_STATUS_ACCESS_DENIED; + } /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) + if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { + DEBUG(10, ("_lsa_create_account: The use is not a Domain Admin, deny access!\n")); return NT_STATUS_ACCESS_DENIED; + } - if ( is_privileged_sid( &q_u->sid.sid ) ) + if ( is_privileged_sid( &q_u->sid.sid ) ) { + DEBUG(10, ("_lsa_create_account: Policy account already exists!\n")); return NT_STATUS_OBJECT_NAME_COLLISION; + } /* associate the user/group SID with the (unique) handle. */ @@ -1582,6 +1588,7 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR if (!create_policy_hnd(p, &r_u->pol, free_lsa_info, (void *)info)) return NT_STATUS_OBJECT_NAME_NOT_FOUND; + DEBUG(10, ("_lsa_create_account: call privileges code to create an account\n")); return privilege_create_account( &info->sid ); } @@ -1676,7 +1683,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA return NT_STATUS_INVALID_HANDLE; if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL)) - return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_OK; /* 0x01 -> Log on locally @@ -1727,7 +1734,6 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u struct lsa_info *info = NULL; SE_PRIV mask; PRIVILEGE_SET *set = NULL; - struct current_user user; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) @@ -1736,8 +1742,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u /* check to see if the pipe_user is root or a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1768,7 +1773,6 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP struct lsa_info *info = NULL; SE_PRIV mask; PRIVILEGE_SET *set = NULL; - struct current_user user; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info)) @@ -1777,8 +1781,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP /* check to see if the pipe_user is root or a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1929,7 +1932,6 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R DOM_SID sid; fstring privname; UNISTR4_ARRAY *uni_privnames = q_u->rights; - struct current_user user; /* find the connection policy handle. */ @@ -1939,8 +1941,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; @@ -1987,7 +1988,6 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, DOM_SID sid; fstring privname; UNISTR4_ARRAY *uni_privnames = q_u->rights; - struct current_user user; /* find the connection policy handle. */ @@ -1997,8 +1997,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, /* check to see if the pipe_user is a Domain Admin since account_pol.tdb was already opened as root, this is all we have */ - get_current_user( &user, p ); - if ( user.ut.uid != sec_initial_uid() + if ( p->pipe_user.ut.uid != sec_initial_uid() && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) ) { return NT_STATUS_ACCESS_DENIED; diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 812a720d90..e2c5e865ed 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -46,6 +46,11 @@ static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth) auth->a_u.auth_ntlmssp_state = NULL; } +static DATA_BLOB generic_session_key(void) +{ + return data_blob("SystemLibraryDTC", 16); +} + /******************************************************************* Generate the next PDU to be returned from the data in p->rdata. Handle NTLMSSP. @@ -610,16 +615,6 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) ZERO_STRUCT(reply); - memset(p->user_name, '\0', sizeof(p->user_name)); - memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); - memset(p->domain, '\0', sizeof(p->domain)); - memset(p->wks, '\0', sizeof(p->wks)); - - /* Set up for non-authenticated user. */ - TALLOC_FREE(p->pipe_user.nt_user_token); - p->pipe_user.ut.ngroups = 0; - SAFE_FREE( p->pipe_user.ut.groups); - /* this has to be done as root in order to verify the password */ become_root(); status = auth_ntlmssp_update(a, *p_resp_blob, &reply); @@ -632,6 +627,12 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) return False; } + if (a->server_info->ptok == NULL) { + DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n")); + p->pipe_user.nt_user_token = NULL; + return False; + } + /* Finally - if the pipe negotiated integrity (sign) or privacy (seal) ensure the underlying NTLMSSP flags are also set. If not we should refuse the bind. */ @@ -653,13 +654,9 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) } } - fstrcpy(p->user_name, a->ntlmssp_state->user); - fstrcpy(p->pipe_user_name, a->server_info->unix_name); - fstrcpy(p->domain, a->ntlmssp_state->domain); - fstrcpy(p->wks, a->ntlmssp_state->workstation); - DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n", - p->user_name, p->domain, p->wks)); + a->ntlmssp_state->user, a->ntlmssp_state->domain, + a->ntlmssp_state->workstation)); /* * Store the UNIX credential data (uid/gid pair) in the pipe structure. @@ -669,11 +666,13 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) p->pipe_user.ut.gid = a->server_info->gid; /* - * Copy the session key from the ntlmssp state. + * We're an authenticated bind over smb, so the session key needs to + * be set to "SystemLibraryDTC". Weird, but this is what Windows + * does. See the RPC-SAMBA3SESSIONKEY. */ data_blob_free(&p->session_key); - p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length); + p->session_key = generic_session_key(); if (!p->session_key.data) { return False; } @@ -688,23 +687,21 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) } } - if (a->server_info->ptok) { - p->pipe_user.nt_user_token = - dup_nt_token(NULL, a->server_info->ptok); - if (!p->pipe_user.nt_user_token) { - DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n")); - data_blob_free(&p->session_key); - SAFE_FREE(p->pipe_user.ut.groups); - return False; - } - - } else { + if (!a->server_info->ptok) { DEBUG(1,("pipe_ntlmssp_verify_final: Error: Authmodule failed to provide nt_user_token\n")); data_blob_free(&p->session_key); SAFE_FREE(p->pipe_user.ut.groups); return False; } + p->pipe_user.nt_user_token = dup_nt_token(NULL, a->server_info->ptok); + if (!p->pipe_user.nt_user_token) { + DEBUG(1,("pipe_ntlmssp_verify_final: dup_nt_token failed.\n")); + data_blob_free(&p->session_key); + SAFE_FREE(p->pipe_user.ut.groups); + return False; + } + return True; } @@ -1361,8 +1358,21 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, * JRA. Should we also copy the schannel session key into the pipe session key p->session_key * here ? We do that for NTLMSSP, but the session key is already set up from the vuser * struct of the person who opened the pipe. I need to test this further. JRA. + * + * VL. As we are mapping this to guest set the generic key + * "SystemLibraryDTC" key here. It's a bit difficult to test against + * W2k3, as it does not allow schannel binds against SAMR and LSA + * anymore. */ + data_blob_free(&p->session_key); + p->session_key = generic_session_key(); + if (p->session_key.data == NULL) { + DEBUG(0, ("pipe_schannel_auth_bind: Could not alloc session" + " key\n")); + return False; + } + init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); @@ -1391,6 +1401,12 @@ static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, p->auth.auth_data_free_func = NULL; p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; + if (!set_current_user_guest(&p->pipe_user)) { + DEBUG(1, ("pipe_schannel_auth_bind: Could not set guest " + "token\n")); + return False; + } + p->pipe_bound = True; return True; @@ -1641,11 +1657,18 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) case RPC_ANONYMOUS_AUTH_TYPE: /* Unauthenticated bind request. */ + /* Get the authenticated pipe user from current_user */ + if (!copy_current_user(&p->pipe_user, ¤t_user)) { + DEBUG(10, ("Could not copy current user\n")); + goto err_exit; + } /* We're finished - no more packets. */ p->auth.auth_type = PIPE_AUTH_TYPE_NONE; /* We must set the pipe auth_level here also. */ p->auth.auth_level = PIPE_AUTH_LEVEL_NONE; p->pipe_bound = True; + /* The session key was initialized from the SMB + * session in make_internal_rpc_pipe_p */ break; default: @@ -2148,23 +2171,6 @@ BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss return True; } -/**************************************************************************** - Return a user struct for a pipe user. -****************************************************************************/ - -struct current_user *get_current_user(struct current_user *user, pipes_struct *p) -{ - if (p->pipe_bound && - (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP || - (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { - memcpy(user, &p->pipe_user, sizeof(struct current_user)); - } else { - memcpy(user, ¤t_user, sizeof(struct current_user)); - } - - return user; -} - /**************************************************************************** Find the set of RPC functions associated with this context_id ****************************************************************************/ @@ -2219,9 +2225,7 @@ BOOL api_pipe_request(pipes_struct *p) BOOL changed_user = False; PIPE_RPC_FNS *pipe_fns; - if (p->pipe_bound && - ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) || - (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { + if (p->pipe_bound) { if(!become_authenticated_pipe_user(p)) { prs_mem_free(&p->out_data.rdata); return False; @@ -2373,6 +2377,9 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) case PI_EVENTLOG: eventlog_get_pipe_fns( &cmds, &n_cmds ); break; + case PI_UNIXINFO: + unixinfo_get_pipe_fns( &cmds, &n_cmds ); + break; case PI_NTSVCS: ntsvcs_get_pipe_fns( &cmds, &n_cmds ); break; diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 9cc8b72546..8aa5bb3e6d 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -351,8 +351,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, /* Store the session key and NT_TOKEN */ if (vuser) { p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length); - p->pipe_user.nt_user_token = dup_nt_token( - NULL, vuser->nt_user_token); } /* @@ -1169,6 +1167,13 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p) p->name, p->pnum, pipes_open)); DLIST_REMOVE(Pipes, p); + + /* TODO: Remove from pipe open db */ + + if ( !delete_pipe_opendb( p ) ) { + DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s " + "pipe from open db.\n", p->name)); + } ZERO_STRUCTP(p); diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index e045de5639..2e0b355db5 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -1435,7 +1435,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO } } - init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status); + init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, type, r_u->status); DEBUG(5,("_samr_lookup_names: %d\n", __LINE__)); @@ -2508,7 +2508,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, } DEBUG(5, ("_samr_create_user: %s can add this account : %s\n", - p->pipe_user_name, can_add_account ? "True":"False" )); + uidtoname(p->pipe_user.ut.uid), + can_add_account ? "True":"False" )); /********** BEGIN Admin BLOCK **********/ @@ -3110,9 +3111,11 @@ static NTSTATUS set_user_info_21(TALLOC_CTX *mem_ctx, SAM_USER_INFO_21 *id21, } /* we need to separately check for an account rename first */ + if (rpcstr_pull(new_name, id21->uni_user_name.buffer, - sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) && - (!strequal(new_name, pdb_get_username(pwd)))) { + sizeof(new_name), id21->uni_user_name.uni_str_len*2, 0) + && (!strequal(new_name, pdb_get_username(pwd)))) + { /* check to see if the new username already exists. Note: we can't reliably lock all backends, so there is potentially the @@ -3435,7 +3438,8 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE } DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", - p->pipe_user_name, has_enough_rights ? "" : " not")); + uidtoname(p->pipe_user.ut.uid), + has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ @@ -3593,7 +3597,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ } DEBUG(5, ("_samr_set_userinfo2: %s does%s possess sufficient rights\n", - p->pipe_user_name, has_enough_rights ? "" : " not")); + uidtoname(p->pipe_user.ut.uid), + has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index 2b65eb210f..c4bec79c9c 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/rpc_server/srv_samr_util.c @@ -195,14 +195,13 @@ void copy_id21_to_sam_passwd(struct samu *to, SAM_USER_INFO_21 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); - DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); + DEBUG(10,("INFO_21 UNI_COMMENT: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to, new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && @@ -445,14 +444,13 @@ void copy_id23_to_sam_passwd(struct samu *to, SAM_USER_INFO_23 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); DEBUG(10,("INFO_23 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && @@ -683,14 +681,13 @@ void copy_id25_to_sam_passwd(struct samu *to, SAM_USER_INFO_25 *from) pdb_set_workstations(to , new_string, PDB_CHANGED); } - /* is this right? */ - if ((from->fields_present & ACCT_ADMIN_DESC) && - (from->hdr_unknown_str.buffer)) { - old_string = pdb_get_unknown_str(to); - new_string = unistr2_static(&from->uni_unknown_str); + if ((from->fields_present & ACCT_COMMENT) && + (from->hdr_comment.buffer)) { + old_string = pdb_get_comment(to); + new_string = unistr2_static(&from->uni_comment); DEBUG(10,("INFO_25 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string)); if (STRING_CHANGED) - pdb_set_unknown_str(to , new_string, PDB_CHANGED); + pdb_set_comment(to , new_string, PDB_CHANGED); } if ((from->fields_present & ACCT_CALLBACK) && diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 0281e3da0c..3dbad208cc 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -331,7 +331,7 @@ WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename ) /* go ahead and re-read the services immediately */ reload_services( False ); - if ( lp_servicenumber( sharename ) < 0 ) + if ( !share_defined( sharename ) ) return WERR_ACCESS_DENIED; return WERR_OK; @@ -1509,7 +1509,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, fstring name; int snum; - struct current_user user; Printer_entry *Printer=NULL; if ( !q_u->printername ) @@ -1533,8 +1532,6 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, return WERR_INVALID_PRINTER_NAME; } - get_current_user(&user, p); - /* * First case: the user is opening the print server: * @@ -1599,12 +1596,12 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ((user.ut.uid != 0) && - !user_has_privileges(user.nt_user_token, + if ((p->pipe_user.ut.uid != 0) && + !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) && !token_contains_name_in_list( - uidtoname(user.ut.uid), NULL, - user.nt_user_token, + uidtoname(p->pipe_user.ut.uid), NULL, + p->pipe_user.nt_user_token, lp_printer_admin(snum))) { close_printer_handle(p, handle); return WERR_ACCESS_DENIED; @@ -1657,9 +1654,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, return WERR_ACCESS_DENIED; } - if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token, - snum) || - !print_access_check(&user, snum, + if (!user_ok_token(uidtoname(p->pipe_user.ut.uid), + p->pipe_user.nt_user_token, snum) || + !print_access_check(&p->pipe_user, snum, printer_default->access_required)) { DEBUG(3, ("access DENIED for printer open\n")); close_printer_handle(p, handle); @@ -1953,20 +1950,17 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER NT_PRINTER_DRIVER_INFO_LEVEL info; NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; - struct current_user user; WERROR status; WERROR status_win2k = WERR_ACCESS_DENIED; SE_PRIV se_printop = SE_PRINT_OPERATOR; - get_current_user(&user, p); - /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ( (user.ut.uid != 0) - && !user_has_privileges(user.nt_user_token, &se_printop ) - && !token_contains_name_in_list( uidtoname(user.ut.uid), - NULL, user.nt_user_token, lp_printer_admin(-1)) ) + if ( (p->pipe_user.ut.uid != 0) + && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) + && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), + NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) { return WERR_ACCESS_DENIED; } @@ -2013,7 +2007,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER /* if we get to here, we now have 2 driver info structures to remove */ /* remove the Win2k driver first*/ - status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False ); + status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False ); free_a_printer_driver( info_win2k, 3 ); /* this should not have failed---if it did, report to client */ @@ -2025,7 +2019,7 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER } } - status = delete_printer_driver(info.info_3, &user, version, False); + status = delete_printer_driver(info.info_3, &p->pipe_user, version, False); /* if at least one of the deletes succeeded return OK */ @@ -2051,20 +2045,17 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV int version; uint32 flags = q_u->delete_flags; BOOL delete_files; - struct current_user user; WERROR status; WERROR status_win2k = WERR_ACCESS_DENIED; SE_PRIV se_printop = SE_PRINT_OPERATOR; - get_current_user(&user, p); - /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege, and not a printer admin, then fail */ - if ( (user.ut.uid != 0) - && !user_has_privileges(user.nt_user_token, &se_printop ) - && !token_contains_name_in_list( uidtoname(user.ut.uid), - NULL, user.nt_user_token, lp_printer_admin(-1)) ) + if ( (p->pipe_user.ut.uid != 0) + && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop ) + && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid), + NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) ) { return WERR_ACCESS_DENIED; } @@ -2150,7 +2141,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV /* if we get to here, we now have 2 driver info structures to remove */ /* remove the Win2k driver first*/ - status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files); + status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files); free_a_printer_driver( info_win2k, 3 ); /* this should not have failed---if it did, report to client */ @@ -2160,7 +2151,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV } } - status = delete_printer_driver(info.info_3, &user, version, delete_files); + status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files); if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) ) status = WERR_OK; @@ -4073,7 +4064,7 @@ static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode Create a DEVMODE struct. Returns malloced memory. ****************************************************************************/ -DEVICEMODE *construct_dev_mode(int snum) +DEVICEMODE *construct_dev_mode(const char *servicename) { NT_PRINTER_INFO_LEVEL *printer = NULL; DEVICEMODE *devmode = NULL; @@ -4082,7 +4073,7 @@ DEVICEMODE *construct_dev_mode(int snum) DEBUGADD(8,("getting printer characteristics\n")); - if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)))) + if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename))) return NULL; if ( !printer->info_2->devmode ) { @@ -4154,7 +4145,7 @@ static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *p printer->cjobs = count; /* jobs */ printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */ - if ( !(printer->devmode = construct_dev_mode(snum)) ) + if ( !(printer->devmode = construct_dev_mode(lp_const_servicename(snum))) ) DEBUG(8, ("Returning NULL Devicemode!\n")); printer->secdesc = NULL; @@ -5640,15 +5631,12 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S pstring jobname; fstring datatype; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - struct current_user user; if (!Printer) { DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; } - get_current_user(&user, p); - /* * a nice thing with NT is it doesn't listen to what you tell it. * when asked to send _only_ RAW datas, it tries to send datas @@ -5672,7 +5660,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname)); - Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode); + Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode); /* An error occured in print_job_start() so return an appropriate NT error code. */ @@ -5745,13 +5733,10 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R static WERROR control_printer(POLICY_HND *handle, uint32 command, pipes_struct *p) { - struct current_user user; int snum; WERROR errcode = WERR_BADFUNC; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - get_current_user(&user, p); - if (!Printer) { DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle))); return WERR_BADFID; @@ -5762,18 +5747,18 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command, switch (command) { case PRINTER_CONTROL_PAUSE: - if (print_queue_pause(&user, snum, &errcode)) { + if (print_queue_pause(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; case PRINTER_CONTROL_RESUME: case PRINTER_CONTROL_UNPAUSE: - if (print_queue_resume(&user, snum, &errcode)) { + if (print_queue_resume(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; case PRINTER_CONTROL_PURGE: - if (print_queue_purge(&user, snum, &errcode)) { + if (print_queue_purge(&p->pipe_user, snum, &errcode)) { errcode = WERR_OK; } break; @@ -5795,7 +5780,6 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R POLICY_HND *handle = &q_u->handle; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); int snum; - struct current_user user; WERROR errcode = WERR_OK; if (!Printer) { @@ -5806,9 +5790,7 @@ WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R if (!get_printer_snum(p, handle, &snum)) return WERR_BADFID; - get_current_user( &user, p ); - - print_job_delete( &user, snum, Printer->jobid, &errcode ); + print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode ); return errcode; } @@ -6018,7 +6000,9 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer) SE_PRIV se_printop = SE_PRINT_OPERATOR; BOOL is_print_op = False; - standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine)); + standard_sub_basic(current_user_info.smb_name, + current_user_info.domain, + 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, @@ -6544,7 +6528,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, /* this should not be a failure condition if the devmode is NULL */ - devmode = construct_dev_mode(snum); + devmode = construct_dev_mode(lp_const_servicename(snum)); for (i=0; i<*returned; i++) fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode); @@ -6664,7 +6648,6 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u uint32 jobid = q_u->jobid; uint32 command = q_u->command; - struct current_user user; int snum; WERROR errcode = WERR_BADFUNC; @@ -6676,23 +6659,21 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u return WERR_INVALID_PRINTER_NAME; } - get_current_user(&user, p); - switch (command) { case JOB_CONTROL_CANCEL: case JOB_CONTROL_DELETE: - if (print_job_delete(&user, snum, jobid, &errcode)) { + if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; case JOB_CONTROL_PAUSE: - if (print_job_pause(&user, snum, jobid, &errcode)) { + if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; case JOB_CONTROL_RESTART: case JOB_CONTROL_RESUME: - if (print_job_resume(&user, snum, jobid, &errcode)) { + if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) { errcode = WERR_OK; } break; @@ -7618,26 +7599,23 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info; 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); - if (!convert_printer_driver_info(info, &driver, level)) { err = WERR_NOMEM; goto done; } DEBUG(5,("Cleaning driver's information\n")); - err = clean_up_driver_struct(driver, level, &user); + err = clean_up_driver_struct(driver, level, &p->pipe_user); if (!W_ERROR_IS_OK(err)) goto done; DEBUG(5,("Moving driver to final destination\n")); - if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) { + if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) { goto done; } @@ -8777,7 +8755,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, */ if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) ) - devmode = construct_dev_mode(snum); + devmode = construct_dev_mode(lp_const_servicename(snum)); else { if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) { ZERO_STRUCTP( devmode ); diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c index 0b4eac5cc7..e4f85d0bdb 100644 --- a/source3/rpc_server/srv_srvsvc.c +++ b/source3/rpc_server/srv_srvsvc.c @@ -6,6 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Jim McDonough 2003. + * Copyright (C) Gera;d (Jerry) Carter 2006. * * 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 @@ -550,6 +551,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p) return True; } +/******************************************************************* +*******************************************************************/ + +static BOOL api_srv_net_file_close(pipes_struct *p) +{ + SRV_Q_NET_FILE_CLOSE q_u; + SRV_R_NET_FILE_CLOSE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* Unmarshall the net file set info from Win9x */ + if(!srv_io_q_net_file_close("", &q_u, data, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n")); + return False; + } + + r_u.status = _srv_net_file_close(p, &q_u, &r_u); + + if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) { + DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n")); + return False; + } + + return True; +} + /******************************************************************* \PIPE\srvsvc commands ********************************************************************/ @@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] = { "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 } + { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc }, + { "SRV_NET_FILE_CLOSE" , SRV_NET_FILE_CLOSE , api_srv_net_file_close } }; void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index a936ef5870..12a86ce9f3 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -4,6 +4,7 @@ * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Jeremy Allison 2001. * Copyright (C) Nigel Williams 2001. + * Copyright (C) Gerald (Jerry) Carter 2006. * * 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,10 +26,179 @@ #include "includes.h" extern struct generic_mapping file_generic_mapping; +extern userdom_struct current_user_info; #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV +/* Use for enumerating connections, pipes, & files */ + +struct file_enum_count { + TALLOC_CTX *ctx; + int count; + FILE_INFO_3 *info; +}; + +struct sess_file_count { + pid_t pid; + uid_t uid; + int count; +}; + +/**************************************************************************** + Count the entries belonging to a service in the connection db. +****************************************************************************/ + +static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p) +{ + struct pipe_open_rec prec; + struct file_enum_count *fenum = (struct file_enum_count *)p; + + if (dbuf.dsize != sizeof(struct pipe_open_rec)) + return 0; + + memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec)); + + if ( process_exists(prec.pid) ) { + FILE_INFO_3 *f; + int i = fenum->count; + pstring fullpath; + + snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name ); + + f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 ); + if ( !f ) { + DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1)); + return 1; + } + fenum->info = f; + + + init_srv_file_info3( &fenum->info[i], + (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum), + (FILE_READ_DATA|FILE_WRITE_DATA), + 0, + uidtoname( prec.uid ), + fullpath ); + + fenum->count++; + } + + return 0; +} + +/******************************************************************* +********************************************************************/ + +static WERROR net_enum_pipes( TALLOC_CTX *ctx, FILE_INFO_3 **info, + uint32 *count, uint32 resume ) +{ + struct file_enum_count fenum; + TDB_CONTEXT *conn_tdb = conn_tdb_ctx(); + + if ( !conn_tdb ) { + DEBUG(0,("net_enum_pipes: Failed to retrieve the connections tdb handle!\n")); + return WERR_ACCESS_DENIED; + } + + fenum.ctx = ctx; + fenum.count = *count; + fenum.info = *info; + + if (tdb_traverse(conn_tdb, pipe_enum_fn, &fenum) == -1) { + DEBUG(0,("net_enum_pipes: traverse of connections.tdb failed with error %s.\n", + tdb_errorstr(conn_tdb) )); + return WERR_NOMEM; + } + + *info = fenum.info; + *count = fenum.count; + + return WERR_OK;} + +/******************************************************************* +********************************************************************/ + +/* global needed to make use of the share_mode_forall() callback */ +static struct file_enum_count f_enum_cnt; + +static void enum_file_fn( const struct share_mode_entry *e, + const char *sharepath, const char *fname ) +{ + struct file_enum_count *fenum = &f_enum_cnt; + + /* If the pid was not found delete the entry from connections.tdb */ + + if ( process_exists(e->pid) ) { + FILE_INFO_3 *f; + int i = fenum->count; + files_struct fsp; + struct byte_range_lock *brl; + int num_locks = 0; + pstring fullpath; + uint32 permissions; + + f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 ); + if ( !f ) { + DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1)); + return; + } + fenum->info = f; + + /* need to count the number of locks on a file */ + + ZERO_STRUCT( fsp ); + fsp.dev = e->dev; + fsp.inode = e->inode; + + if ( (brl = brl_get_locks(NULL,&fsp)) != NULL ) { + num_locks = brl->num_locks; + TALLOC_FREE( brl ); + } + + if ( strcmp( fname, "." ) == 0 ) { + pstr_sprintf( fullpath, "C:%s", sharepath ); + } else { + pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname ); + } + string_replace( fullpath, '/', '\\' ); + + /* mask out create (what ever that is) */ + permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA); + + /* now fill in the FILE_INFO_3 struct */ + init_srv_file_info3( &fenum->info[i], + e->share_file_id, + permissions, + num_locks, + uidtoname(e->uid), + fullpath ); + + fenum->count++; + } + + return; + +} + +/******************************************************************* +********************************************************************/ + +static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info, + uint32 *count, uint32 resume ) +{ + f_enum_cnt.ctx = ctx; + f_enum_cnt.count = *count; + f_enum_cnt.info = *info; + + share_mode_forall( enum_file_fn ); + + *info = f_enum_cnt.info; + *count = f_enum_cnt.count; + + return WERR_OK; +} + /******************************************************************* Utility function to get the 'type' of a share from an snum. ********************************************************************/ @@ -70,11 +240,16 @@ static void init_srv_share_info_0(pipes_struct *p, SRV_SHARE_INFO_0 *sh0, int sn static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int snum) { + connection_struct *conn = p->conn; pstring remark; char *net_name = lp_servicename(snum); pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); init_srv_share_info1(&sh1->info_1, net_name, get_share_type(snum), remark); init_srv_share_info1_str(&sh1->info_1_str, net_name, remark); @@ -86,15 +261,21 @@ static void init_srv_share_info_1(pipes_struct *p, SRV_SHARE_INFO_1 *sh1, int sn static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int snum) { + connection_struct *conn = p->conn; pstring remark; pstring path; pstring passwd; int max_connections = lp_max_connections(snum); uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff; - + int count = 0; char *net_name = lp_servicename(snum); + pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); pstrcpy(path, "C:"); pstrcat(path, lp_pathname(snum)); @@ -107,7 +288,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn pstrcpy(passwd, ""); - init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, max_uses, 1, path, passwd); + count = count_current_connections( net_name, False ); + init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), + remark, 0, max_uses, count, path, passwd); + init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd); } @@ -179,11 +363,16 @@ out: static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, int snum) { + connection_struct *conn = p->conn; pstring remark; const char *net_name = lp_servicename(snum); pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark, sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); init_srv_share_info501(&sh501->info_501, net_name, get_share_type(snum), remark, (lp_csc_policy(snum) << 4)); init_srv_share_info501_str(&sh501->info_501_str, net_name, remark); @@ -195,6 +384,7 @@ static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, int snum) { + connection_struct *conn = p->conn; pstring net_name; pstring remark; pstring path; @@ -208,7 +398,11 @@ 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,sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); pstrcpy(path, "C:"); pstrcat(path, lp_pathname(snum)); @@ -233,10 +427,15 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502, static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh1004, int snum) { + connection_struct *conn = p->conn; pstring remark; pstrcpy(remark, lp_comment(snum)); - standard_sub_conn(p->conn, remark, sizeof(remark)); + standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, + conn->connectpath, conn->gid, + get_current_username(), + current_user_info.domain, + remark, sizeof(remark)); ZERO_STRUCTP(sh1004); @@ -632,16 +831,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I r_n->status = status; } -/******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ - -static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name) -{ - init_srv_sess_info0(se0, name); - init_srv_sess_info0_str(str0, name); -} - /******************************************************************* fill in a sess info level 0 structure. ********************************************************************/ @@ -662,11 +851,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], session_list[(*snum)].remote_machine); - - /* move on to creating next session */ - /* move on to creating next sess */ + init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine); num_entries++; } @@ -687,17 +872,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto } /******************************************************************* - fill in a sess info level 1 structure. - ********************************************************************/ +********************************************************************/ -static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1, - char *name, char *user, - uint32 num_opens, - uint32 open_time, uint32 idle_time, - uint32 usr_flgs) +/* global needed to make use of the share_mode_forall() callback */ +static struct sess_file_count s_file_cnt; + +static void sess_file_fn( const struct share_mode_entry *e, + const char *sharepath, const char *fname ) { - init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs); - init_srv_sess_info1_str(str1, name, user); + struct sess_file_count *sess = &s_file_cnt; + + if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) { + sess->count++; + } + + return; +} + +/******************************************************************* +********************************************************************/ + +static int net_count_files( uid_t uid, pid_t pid ) +{ + s_file_cnt.count = 0; + s_file_cnt.uid = uid; + s_file_cnt.pid = pid; + + share_mode_forall( sess_file_fn ); + + return s_file_cnt.count; } /******************************************************************* @@ -708,43 +911,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto { struct sessionid *session_list; uint32 num_entries = 0; - (*stot) = list_sessions(&session_list); + time_t now = time(NULL); + if ( !snum ) { + ss1->num_entries_read = 0; + ss1->ptr_sess_info = 0; + ss1->num_entries_read2 = 0; + + (*stot) = 0; + + return; + } + if (ss1 == NULL) { (*snum) = 0; - SAFE_FREE(session_list); return; } - DEBUG(5,("init_srv_sess_1_ss1\n")); - - 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], - 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 */ - num_entries++; - } + (*stot) = list_sessions(&session_list); + - ss1->num_entries_read = num_entries; - ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; - ss1->num_entries_read2 = num_entries; - - if ((*snum) >= (*stot)) { - (*snum) = 0; + for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) { + uint32 num_files; + uint32 connect_time; + struct passwd *pw = sys_getpwnam(session_list[*snum].username); + BOOL guest; + + if ( !pw ) { + DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n", + session_list[*snum].username)); + continue; } - - } else { - ss1->num_entries_read = 0; - ss1->ptr_sess_info = 0; - ss1->num_entries_read2 = 0; - - (*stot) = 0; + + connect_time = (uint32)(now - session_list[*snum].connect_start); + num_files = net_count_files(pw->pw_uid, session_list[*snum].pid); + guest = strequal( session_list[*snum].username, lp_guestaccount() ); + + init_srv_sess_info1( &ss1->info_1[num_entries], + session_list[*snum].remote_machine, + session_list[*snum].username, + num_files, + connect_time, + 0, + guest); + num_entries++; + } + + ss1->num_entries_read = num_entries; + ss1->ptr_sess_info = num_entries > 0 ? 1 : 0; + ss1->num_entries_read2 = num_entries; + + if ((*snum) >= (*stot)) { + (*snum) = 0; } SAFE_FREE(session_list); @@ -964,66 +1182,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n, makes a SRV_R_NET_FILE_ENUM structure. ********************************************************************/ -static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr, - int switch_value, uint32 *resume_hnd, - uint32 *total_entries) +static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd ) { - 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 */ + TALLOC_CTX *ctx = get_talloc_ctx(); + SRV_FILE_INFO_CTR *ctr = &r->ctr; - ctr->switch_value = switch_value; - ctr->num_entries = *total_entries - *resume_hnd; + /* TODO -- Windows enumerates + (b) active pipes + (c) open directories and files */ + + r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd ); + if ( !W_ERROR_IS_OK(r->status)) + goto done; + + r->level = ctr->level = 3; + r->total_entries = ctr->num_entries; + /* ctr->num_entries = r->total_entries - resume_hnd; */ ctr->num_entries2 = ctr->num_entries; + ctr->ptr_file_info = 1; - switch (switch_value) { - case 3: { - int i; - if (*total_entries > 0) { - ctr->ptr_entries = 1; - ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries); - } - for (i=0 ;inum_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_entries = 0; - status = WERR_UNKNOWN_LEVEL; - break; - } + r->status = WERR_OK; - return status; +done: + if ( ctr->num_entries > 0 ) + ctr->ptr_entries = 1; + + init_enum_hnd(&r->enum_hnd, 0); + + return r->status; } /******************************************************************* - makes a SRV_R_NET_FILE_ENUM structure. -********************************************************************/ +*******************************************************************/ -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) +WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u) { - DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__)); - - r_n->file_level = file_level; - if (file_level == 0) - r_n->status = WERR_UNKNOWN_LEVEL; - else - 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; - - init_enum_hnd(&r_n->enum_hnd, resume_hnd); + switch ( q_u->level ) { + case 3: + return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) ); + default: + return WERR_UNKNOWN_LEVEL; + } + + return WERR_OK; } /******************************************************************* @@ -1109,25 +1314,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R return r_u->status; } -/******************************************************************* -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) -{ - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - /* set up the */ - 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); - - DEBUG(5,("srv_net_file_enum: %d\n", __LINE__)); - - return r_u->status; -} - /******************************************************************* net conn enum ********************************************************************/ @@ -1185,7 +1371,6 @@ net sess del WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u) { struct sessionid *session_list; - struct current_user user; int num_sessions, snum; fstring username; fstring machine; @@ -1205,11 +1390,9 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES r_u->status = WERR_ACCESS_DENIED; - get_current_user(&user, p); - /* fail out now if you are not root or not a domain admin */ - if ((user.ut.uid != sec_initial_uid()) && + if ((p->pipe_user.ut.uid != sec_initial_uid()) && ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) { goto done; @@ -1220,7 +1403,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) && strequal(session_list[snum].remote_machine, machine)) { - if (user.ut.uid != sec_initial_uid()) { + if (p->pipe_user.ut.uid != sec_initial_uid()) { not_root = True; become_root(); } @@ -1337,7 +1520,6 @@ char *valid_share_pathname(char *dos_pathname) WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, SRV_R_NET_SHARE_SET_INFO *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1374,13 +1556,11 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); /* fail out now if you are not root and not a disk op */ - if ( user.ut.uid != sec_initial_uid() && !is_disk_op ) + if ( p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; switch (q_u->info_level) { @@ -1525,7 +1705,6 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u) { - struct current_user user; pstring command; fstring share_name; fstring comment; @@ -1543,11 +1722,9 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S r_u->parm_error = 0; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_add_share_cmd() || !*lp_add_share_cmd()) { @@ -1682,7 +1859,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_SHARE_DEL *r_u) { - struct current_user user; pstring command; fstring share_name; int ret; @@ -1710,11 +1886,9 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S if (lp_print_ok(snum)) return WERR_ACCESS_DENIED; - get_current_user(&user,p); - is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop ); - if (user.ut.uid != sec_initial_uid() && !is_disk_op ) + if (p->pipe_user.ut.uid != sec_initial_uid() && !is_disk_op ) return WERR_ACCESS_DENIED; if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) { @@ -1826,7 +2000,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1839,10 +2012,8 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1872,18 +2043,18 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC goto error_exit; } - fsp = open_file_stat(conn, filename, &st); - if (!fsp) { + nt_status = open_file_stat(conn, filename, &st, &fsp); + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, READ_CONTROL_ACCESS, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -1908,7 +2079,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -1921,7 +2092,7 @@ error_exit: unbecome_user(); if (conn) - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; } @@ -1941,7 +2112,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ SMB_STRUCT_STAT st; BOOL bad_path; NTSTATUS nt_status; - struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; @@ -1954,10 +2124,8 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ /* Null password is ok - we are already an authenticated user... */ null_pw = data_blob(NULL, 0); - get_current_user(&user, p); - become_root(); - conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", p->pipe_user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1988,19 +2156,19 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ } - fsp = open_file_stat(conn, filename, &st); + nt_status = open_file_stat(conn, filename, &st, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { /* Perhaps it is a directory */ - if (errno == EISDIR) - fsp = open_directory(conn, filename, &st, + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_IS_A_DIRECTORY)) + nt_status = open_directory(conn, filename, &st, FILE_READ_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, - NULL); + NULL, &fsp); - if (!fsp) { + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename)); r_u->status = WERR_ACCESS_DENIED; goto error_exit; @@ -2017,7 +2185,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ close_file(fsp, NORMAL_CLOSE); unbecome_user(); - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); return r_u->status; error_exit: @@ -2031,7 +2199,7 @@ error_exit: } if (conn) { - close_cnum(conn, user.vuid); + close_cnum(conn, p->pipe_user.vuid); } return r_u->status; @@ -2133,7 +2301,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV switch ( q_u->type ) { case 0x9: - rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0); + rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0); if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) { DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename)); return WERR_INVALID_NAME; @@ -2146,3 +2314,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV return WERR_OK; } + + +/******************************************************************** +********************************************************************/ + +WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u) +{ + return WERR_ACCESS_DENIED; +} + diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 6062dcee5c..dd790691d3 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -624,7 +624,7 @@ static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG the client from showing the "Start" button (if of course the services are not running */ - if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) ) + if ( strequal( name, "NETLOGON" ) && ( !share_defined(name) ) ) config->start_type = SVCCTL_DISABLED; else if ( strequal( name, "WINS" ) && ( !lp_wins_support() )) config->start_type = SVCCTL_DISABLED; diff --git a/source3/rpc_server/srv_unixinfo.c b/source3/rpc_server/srv_unixinfo.c new file mode 100644 index 0000000000..f21416dfab --- /dev/null +++ b/source3/rpc_server/srv_unixinfo.c @@ -0,0 +1,163 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines for unixinfo-pipe + * Copyright (C) Volker Lendecke 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is the interface to the rpcunixinfo pipe. */ + +#include "includes.h" +#include "nterr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +static BOOL api_sid_to_uid(pipes_struct *p) +{ + UNIXINFO_Q_SID_TO_UID q_u; + UNIXINFO_R_SID_TO_UID 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 (!unixinfo_io_q_unixinfo_sid_to_uid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_sid_to_uid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_sid_to_uid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_uid_to_sid(pipes_struct *p) +{ + UNIXINFO_Q_UID_TO_SID q_u; + UNIXINFO_R_UID_TO_SID 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 (!unixinfo_io_q_unixinfo_uid_to_sid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_uid_to_sid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_uid_to_sid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_sid_to_gid(pipes_struct *p) +{ + UNIXINFO_Q_SID_TO_GID q_u; + UNIXINFO_R_SID_TO_GID 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 (!unixinfo_io_q_unixinfo_sid_to_gid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_sid_to_gid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_sid_to_gid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_gid_to_sid(pipes_struct *p) +{ + UNIXINFO_Q_GID_TO_SID q_u; + UNIXINFO_R_GID_TO_SID 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 (!unixinfo_io_q_unixinfo_gid_to_sid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_gid_to_sid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_gid_to_sid("", &r_u, rdata, 0)) + return False; + + return True; +} + +static BOOL api_getpwuid(pipes_struct *p) +{ + UNIXINFO_Q_GETPWUID q_u; + UNIXINFO_R_GETPWUID 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 (!unixinfo_io_q_unixinfo_getpwuid("", &q_u, data, 0)) + return False; + + r_u.status = _unixinfo_getpwuid(p, &q_u, &r_u); + + if (!unixinfo_io_r_unixinfo_getpwuid("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* +\pipe\unixinfo commands +********************************************************************/ + +struct api_struct api_unixinfo_cmds[] = { + {"SID_TO_UID", UNIXINFO_SID_TO_UID, api_sid_to_uid }, + {"UID_TO_SID", UNIXINFO_UID_TO_SID, api_uid_to_sid }, + {"SID_TO_GID", UNIXINFO_SID_TO_GID, api_sid_to_gid }, + {"GID_TO_SID", UNIXINFO_GID_TO_SID, api_gid_to_sid }, + {"GETPWUID", UNIXINFO_GETPWUID, api_getpwuid }, +}; + + +void unixinfo_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_unixinfo_cmds; + *n_fns = sizeof(api_unixinfo_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_unixinfo_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, + "unixinfo", "unixinfo", api_unixinfo_cmds, + sizeof(api_unixinfo_cmds) / sizeof(struct api_struct)); +} diff --git a/source3/rpc_server/srv_unixinfo_nt.c b/source3/rpc_server/srv_unixinfo_nt.c new file mode 100644 index 0000000000..79756f20a7 --- /dev/null +++ b/source3/rpc_server/srv_unixinfo_nt.c @@ -0,0 +1,166 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines for unixinfo-pipe + * Copyright (C) Volker Lendecke 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is the interface to the rpcunixinfo pipe. */ + +#include "includes.h" +#include "nterr.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/* Map a sid to a uid */ + +NTSTATUS _unixinfo_sid_to_uid(pipes_struct *p, + UNIXINFO_Q_SID_TO_UID *q_u, + UNIXINFO_R_SID_TO_UID *r_u) +{ + uid_t uid; + + r_u->uid.low = 0; + r_u->uid.high = 0; + + r_u->status = sid_to_uid(&q_u->sid, &uid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED; + if (NT_STATUS_IS_OK(r_u->status)) + r_u->uid.low = uid; + + return r_u->status; +} + +/* Map a uid to a sid */ + +NTSTATUS _unixinfo_uid_to_sid(pipes_struct *p, + UNIXINFO_Q_UID_TO_SID *q_u, + UNIXINFO_R_UID_TO_SID *r_u) +{ + DOM_SID sid; + + r_u->status = NT_STATUS_NO_SUCH_USER; + + if (q_u->uid.high == 0) { + uid_to_sid(&sid, q_u->uid.low); + r_u->status = NT_STATUS_OK; + } + + init_r_unixinfo_uid_to_sid(r_u, + NT_STATUS_IS_OK(r_u->status) ? &sid : NULL); + + return r_u->status; +} + +/* Map a sid to a gid */ + +NTSTATUS _unixinfo_sid_to_gid(pipes_struct *p, + UNIXINFO_Q_SID_TO_GID *q_u, + UNIXINFO_R_SID_TO_GID *r_u) +{ + gid_t gid; + + r_u->gid.low = 0; + r_u->gid.high = 0; + + r_u->status = sid_to_gid(&q_u->sid, &gid) ? NT_STATUS_OK : NT_STATUS_NONE_MAPPED; + if (NT_STATUS_IS_OK(r_u->status)) + r_u->gid.low = gid; + + return r_u->status; +} + +/* Map a gid to a sid */ + +NTSTATUS _unixinfo_gid_to_sid(pipes_struct *p, + UNIXINFO_Q_GID_TO_SID *q_u, + UNIXINFO_R_GID_TO_SID *r_u) +{ + DOM_SID sid; + + r_u->status = NT_STATUS_NO_SUCH_USER; + + if (q_u->gid.high == 0) { + gid_to_sid(&sid, q_u->gid.low); + r_u->status = NT_STATUS_OK; + } + + init_r_unixinfo_gid_to_sid(r_u, + NT_STATUS_IS_OK(r_u->status) ? &sid : NULL); + + return r_u->status; +} + +/* Get unix struct passwd information */ + +NTSTATUS _unixinfo_getpwuid(pipes_struct *p, + UNIXINFO_Q_GETPWUID *q_u, + UNIXINFO_R_GETPWUID *r_u) +{ + int i; + + if (r_u->count > 1023) { + return NT_STATUS_INVALID_PARAMETER; + } + + r_u->info = TALLOC_ARRAY(p->mem_ctx, struct unixinfo_getpwuid, + q_u->count); + + if ((r_u->count > 0) && (r_u->info == NULL)) { + return NT_STATUS_NO_MEMORY; + } + + r_u->status = NT_STATUS_OK; + r_u->count = q_u->count; + + for (i=0; icount; i++) { + struct passwd *pw; + char *homedir, *shell; + ssize_t len1, len2; + + r_u->info[i].status = NT_STATUS_NO_SUCH_USER; + r_u->info[i].homedir = ""; + r_u->info[i].shell = ""; + + if (q_u->uid[i].high != 0) { + DEBUG(10, ("64-bit uids not yet supported...\n")); + continue; + } + + pw = getpwuid(q_u->uid[i].low); + + if (pw == NULL) { + DEBUG(10, ("Did not find uid %d\n", q_u->uid[i].low)); + continue; + } + + len1 = push_utf8_talloc(p->mem_ctx, &homedir, pw->pw_dir); + len2 = push_utf8_talloc(p->mem_ctx, &shell, pw->pw_shell); + + if ((len1 < 0) || (len2 < 0) || (homedir == NULL) || + (shell == NULL)) { + DEBUG(3, ("push_utf8_talloc failed\n")); + r_u->info[i].status = NT_STATUS_NO_MEMORY; + continue; + } + + r_u->info[i].status = NT_STATUS_OK; + r_u->info[i].homedir = homedir; + r_u->info[i].shell = shell; + } + + return r_u->status; +} -- cgit