From d9abdd45339e2d65445a1fd685cb0294729ac4e7 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 26 Jan 2005 21:06:48 +0000 Subject: [PATCH] r5021: Starting to look at final code for 3.0.11rc1. Set VERSION and merged important and/or low risk fixes from 3_0 svn merge -r4905:4907 $SVNURL/branches/SAMBA_3_0 svn merge -r4907:4913 $SVNURL/branches/SAMBA_3_0 svn merge -r4932:4933 $SVNURL/branches/SAMBA_3_0 svn merge -r4933:4946 $SVNURL/branches/SAMBA_3_0 svn merge -r4946:4963 $SVNURL/branches/SAMBA_3_0 svn merge -r4963:4964 $SVNURL/branches/SAMBA_3_0 svn merge -r4964:4965 $SVNURL/branches/SAMBA_3_0 svn merge -r4965:4966 $SVNURL/branches/SAMBA_3_0 svn merge -r4966:4967 $SVNURL/branches/SAMBA_3_0 svn merge -r4967:4970 $SVNURL/branches/SAMBA_3_0 svn merge -r4972:4976 $SVNURL/branches/SAMBA_3_0 svn merge -r4970:4972 $SVNURL/branches/SAMBA_3_0 svn merge -r4976:4988 $SVNURL/branches/SAMBA_3_0 svn merge -r4988:4989 $SVNURL/branches/SAMBA_3_0 svn merge -r4994:4995 $SVNURL/branches/SAMBA_3_0 svn merge -r4995:4996 $SVNURL/branches/SAMBA_3_0 svn merge -r5000:5002 $SVNURL/branches/SAMBA_3_0 svn merge -r5002:5012 $SVNURL/branches/SAMBA_3_0 svn merge -r5012:5014 $SVNURL/branches/SAMBA_3_0 svn merge -r5014:5015 $SVNURL/branches/SAMBA_3_0 --- examples/LDAP/samba.schema | 21 +- packaging/Fedora/filter-requires-samba.sh | 3 +- packaging/RedHat/filter-requires-samba_rh9.sh | 4 +- source/VERSION | 4 +- source/auth/auth_sam.c | 2 +- source/configure.in | 14 +- source/include/auth.h | 4 + source/include/client.h | 1 + source/include/libsmbclient.h | 6 + source/include/rpc_netlogon.h | 3 +- source/include/rpc_secdes.h | 5 +- source/lib/privileges.c | 81 ++- source/lib/smbldap.c | 3 +- source/libsmb/cliconnect.c | 8 +- source/libsmb/libsmbclient.c | 12 +- source/nsswitch/winbindd_cache.c | 2 +- source/passdb/passdb.c | 15 +- source/passdb/pdb_get_set.c | 2 +- source/passdb/pdb_interface.c | 1 + source/printing/print_cups.c | 3 +- source/rpc_parse/parse_net.c | 45 +- source/rpc_server/srv_samr_nt.c | 871 ++++++++++++++------------ source/rpcclient/cmd_lsarpc.c | 38 +- source/rpcclient/cmd_spoolss.c | 12 + source/smbd/open.c | 2 +- source/smbd/oplock.c | 109 +++- source/utils/net_help.c | 2 +- source/utils/net_idmap.c | 2 +- source/utils/net_rpc.c | 8 +- 29 files changed, 764 insertions(+), 519 deletions(-) diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema index 7dc4de54b34..213aa34613f 100644 --- a/examples/LDAP/samba.schema +++ b/examples/LDAP/samba.schema @@ -376,13 +376,13 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) -attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME 'sambaPrivName' - SUP name ) +##attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME 'sambaPrivName' +## SUP name ) -attributetype ( 1.3.6.1.4.1.7165.2.1.52 NAME 'sambaPrivilegeList' - DESC 'Privileges List' - EQUALITY caseIgnoreIA5Match - SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} ) +##attributetype ( 1.3.6.1.4.1.7165.2.1.52 NAME 'sambaPrivilegeList' +## DESC 'Privileges List' +## EQUALITY caseIgnoreIA5Match +## SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} ) attributetype ( 1.3.6.1.4.1.7165.2.1.53 NAME 'sambaTrustFlags' DESC 'Trust Password Flags' @@ -473,8 +473,9 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURA sambaStringListoption $ description ) ) -objectclass ( 1.3.6.1.4.1.7165.2.2.13 NAME 'sambaPrivilege' SUP top AUXILIARY - DESC 'Samba Privilege' - MUST ( sambaSID ) - MAY ( sambaPrivilegeList ) ) +## retired during privilege rewrite +##objectclass ( 1.3.6.1.4.1.7165.2.2.13 NAME 'sambaPrivilege' SUP top AUXILIARY +## DESC 'Samba Privilege' +## MUST ( sambaSID ) +## MAY ( sambaPrivilegeList ) ) diff --git a/packaging/Fedora/filter-requires-samba.sh b/packaging/Fedora/filter-requires-samba.sh index 1ba10a0ee3d..5545cf6c858 100755 --- a/packaging/Fedora/filter-requires-samba.sh +++ b/packaging/Fedora/filter-requires-samba.sh @@ -1,3 +1,4 @@ #!/bin/sh -/usr/lib/rpm/perl.req $* | grep -v "Net::LDAP" +/usr/lib/rpm/perl.req $* | grep -E -v '(Net::LDAP|Crypt::SmbHash|CGI)' + diff --git a/packaging/RedHat/filter-requires-samba_rh9.sh b/packaging/RedHat/filter-requires-samba_rh9.sh index 8378523bceb..5545cf6c858 100755 --- a/packaging/RedHat/filter-requires-samba_rh9.sh +++ b/packaging/RedHat/filter-requires-samba_rh9.sh @@ -1,2 +1,4 @@ #!/bin/sh -/usr/lib/rpm/perl.req $* | egrep -v '(Net::LDAP|CGI)' + +/usr/lib/rpm/perl.req $* | grep -E -v '(Net::LDAP|Crypt::SmbHash|CGI)' + diff --git a/source/VERSION b/source/VERSION index aad6252e56a..3784ff146c2 100644 --- a/source/VERSION +++ b/source/VERSION @@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=11 # e.g. SAMBA_VERSION_PRE_RELEASE=1 # # -> "2.2.9pre1" # ######################################################## -SAMBA_VERSION_PRE_RELEASE=2 +SAMBA_VERSION_PRE_RELEASE= ######################################################## # For 'rc' releases the version will be # @@ -39,7 +39,7 @@ SAMBA_VERSION_PRE_RELEASE=2 # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE= +SAMBA_VERSION_RC_RELEASE=1 ######################################################## # To mark SVN snapshots this should be set to 'yes' # diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c index 4d2fb230027..2633cc92c37 100644 --- a/source/auth/auth_sam.c +++ b/source/auth/auth_sam.c @@ -241,7 +241,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, unbecome_root(); if (ret == False) { - DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); + DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } diff --git a/source/configure.in b/source/configure.in index 330eed79f12..0dcfd9ab1e0 100644 --- a/source/configure.in +++ b/source/configure.in @@ -2655,7 +2655,7 @@ if test x"$with_ads_support" != x"no"; then KRB5_LDFLAGS="-L$withval/lib" FOUND_KRB5=yes if test -x "$withval/bin/krb5-config"; then - KRB5_CONFIG=$withval/bin/krb5-config + KRB5CONFIG=$withval/bin/krb5-config fi ;; esac ], @@ -2665,17 +2665,17 @@ if test x"$with_ads_support" != x"no"; then ################################################# # check for krb5-config from recent MIT and Heimdal kerberos 5 - AC_PATH_PROG(KRB5_CONFIG, krb5-config) + AC_PATH_PROG(KRB5CONFIG, krb5-config) AC_MSG_CHECKING(for working krb5-config) - if test -x "$KRB5_CONFIG"; then + if test -x "$KRB5CONFIG"; then ac_save_CFLAGS=$CFLAGS CFLAGS="";export CFLAGS ac_save_LDFLAGS=$LDFLAGS LDFLAGS="";export LDFLAGS - KRB5_LIBS="`$KRB5_CONFIG --libs gssapi`" - KRB5_LDFLAGS="`$KRB5_CONFIG --libs gssapi | sed s/-lgss.*//`" - KRB5_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" - KRB5_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" + KRB5_LIBS="`$KRB5CONFIG --libs gssapi`" + KRB5_LDFLAGS="`$KRB5CONFIG --libs gssapi | sed s/-lgss.*//`" + KRB5_CFLAGS="`$KRB5CONFIG --cflags | sed s/@INCLUDE_des@//`" + KRB5_CPPFLAGS="`$KRB5CONFIG --cflags | sed s/@INCLUDE_des@//`" CFLAGS=$ac_save_CFLAGS;export CFLAGS LDFLAGS=$ac_save_LDFLAGS;export LDFLAGS FOUND_KRB5=yes diff --git a/source/include/auth.h b/source/include/auth.h index 188cf58643d..91751e71804 100644 --- a/source/include/auth.h +++ b/source/include/auth.h @@ -112,6 +112,10 @@ typedef struct auth_methods const struct auth_usersupplied_info *user_info, auth_serversupplied_info **server_info); + /* If you are using this interface, then you are probably + * getting something wrong. This interface is only for + * security=server, and makes a number of compromises to allow + * that. It is not compatible with being a PDC. */ DATA_BLOB (*get_chal)(const struct auth_context *auth_context, void **my_private_data, TALLOC_CTX *mem_ctx); diff --git a/source/include/client.h b/source/include/client.h index c182544362f..8ae8faf90dc 100644 --- a/source/include/client.h +++ b/source/include/client.h @@ -144,6 +144,7 @@ struct cli_state { uint16 max_recv_frag; BOOL use_kerberos; + BOOL fallback_after_kerberos; BOOL use_spnego; BOOL use_oplocks; /* should we use oplocks? */ diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h index aaa19cb191b..efb04285a7f 100644 --- a/source/include/libsmbclient.h +++ b/source/include/libsmbclient.h @@ -455,9 +455,15 @@ struct _SMBCCTX { * do _NOT_ touch this from your program ! */ struct smbc_internal_data * internal; + + int flags; }; +/* Flags for SMBCCTX->flags */ +#define SMB_CTX_FLAG_USE_KERBEROS (1 << 0) +#define SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS (1 << 1) +#define SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON (1 << 2) /* don't try to do automatic anon login */ /**@ingroup misc * Create a new SBMCCTX (a context). diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h index b865d05b340..3ba1ce6465b 100644 --- a/source/include/rpc_netlogon.h +++ b/source/include/rpc_netlogon.h @@ -190,9 +190,8 @@ typedef struct net_user_info_3 DOM_SID2 dom_sid; /* domain SID */ - uint32 num_other_groups; /* other groups */ - DOM_GID *other_gids; /* group info */ DOM_SID2 *other_sids; /* foreign/trusted domain SIDs */ + uint32 *other_sids_attrib; } NET_USER_INFO_3; diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h index 56145ac024c..1279007220c 100644 --- a/source/include/rpc_secdes.h +++ b/source/include/rpc_secdes.h @@ -401,7 +401,10 @@ typedef struct standard_mapping { #define GENERIC_RIGHTS_USER_WRITE \ (STANDARD_RIGHTS_WRITE_ACCESS | \ SA_RIGHT_USER_CHANGE_PASSWORD | \ - SA_RIGHT_USER_SET_LOC_COM) /* 0x00020044 */ + SA_RIGHT_USER_SET_LOC_COM | \ + SA_RIGHT_USER_SET_ATTRIBUTES | \ + SA_RIGHT_USER_SET_PASSWORD | \ + SA_RIGHT_USER_CHANGE_GROUP_MEM) /* 0x000204e4 */ #define GENERIC_RIGHTS_USER_EXECUTE \ (STANDARD_RIGHTS_EXECUTE_ACCESS | \ diff --git a/source/lib/privileges.c b/source/lib/privileges.c index 628b2dd3251..4feb730feeb 100644 --- a/source/lib/privileges.c +++ b/source/lib/privileges.c @@ -114,7 +114,7 @@ BOOL se_priv_copy( SE_PRIV *dst, const SE_PRIV *src ) combine 2 SE_PRIV structures and store the resulting set in mew_mask ****************************************************************************/ -static void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv ) +void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv ) { int i; @@ -128,7 +128,7 @@ static void se_priv_add( SE_PRIV *mask, const SE_PRIV *addpriv ) in mew_mask ****************************************************************************/ -static void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv ) +void se_priv_remove( SE_PRIV *mask, const SE_PRIV *removepriv ) { int i; @@ -159,6 +159,23 @@ static BOOL se_priv_equal( const SE_PRIV *mask1, const SE_PRIV *mask2 ) return ( memcmp(mask1, mask2, sizeof(SE_PRIV)) == 0 ); } +/*************************************************************************** + check if a SE_PRIV has any assigned privileges +****************************************************************************/ + +static BOOL se_priv_empty( const SE_PRIV *mask ) +{ + SE_PRIV p1; + int i; + + se_priv_copy( &p1, mask ); + + for ( i=0; iprivileges, privilege ); +} + +/**************************************************************************** Convert a LUID to a named string ****************************************************************************/ diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index 7908bc254da..7aeecb89d6f 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -846,7 +846,8 @@ static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_ ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(ldap_state->num_failures ? 2 : 0, - ("failed to bind to server with dn= %s Error: %s\n\t%s\n", + ("failed to bind to server %s with dn=\"%s\" Error: %s\n\t%s\n", + ldap_state->uri, ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc), ld_error ? ld_error : "(unknown)")); SAFE_FREE(ld_error); diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index 29a9533bd24..78cf9028c68 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -757,13 +757,17 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, if (ret){ SAFE_FREE(principal); DEBUG(0, ("Kinit failed: %s\n", error_message(ret))); + if (cli->fallback_after_kerberos) + goto ntlmssp; return ADS_ERROR_KRB5(ret); } } rc = cli_session_setup_kerberos(cli, principal, domain); - SAFE_FREE(principal); - return rc; + if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) { + SAFE_FREE(principal); + return rc; + } } #endif diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c index df9c4ddcadc..8eeadc8a783 100644 --- a/source/libsmb/libsmbclient.c +++ b/source/libsmb/libsmbclient.c @@ -584,6 +584,13 @@ SMBCSRV *smbc_server(SMBCCTX *context, return NULL; } + if (context->flags & SMB_CTX_FLAG_USE_KERBEROS) { + c.use_kerberos = True; + } + if (context->flags & SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) { + c.fallback_after_kerberos = True; + } + c.timeout = context->timeout; /* Force use of port 139 for first try, so browse lists can work */ @@ -648,8 +655,9 @@ SMBCSRV *smbc_server(SMBCCTX *context, password, strlen(password), password, strlen(password), workgroup) && - /* try an anonymous login if it failed */ - !cli_session_setup(&c, "", "", 1,"", 0, workgroup)) { + /* Try an anonymous login if it failed and this was allowed by flags. */ + ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || + !cli_session_setup(&c, "", "", 1,"", 0, workgroup))) { cli_shutdown(&c); errno = EPERM; return NULL; diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index 460ce934cb7..3fc62df005f 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -1243,7 +1243,7 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, (*alias_rids) = TALLOC_ARRAY(mem_ctx, uint32, *num_aliases); - if (!(*alias_rids)) + if ((*num_aliases != 0) && ((*alias_rids) == NULL)) return NT_STATUS_NO_MEMORY; for (i=0; i<(*num_aliases); i++) diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index 1f5e4be6cf6..c7cd59a4c5f 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -759,24 +759,11 @@ BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_na DEBUG(5,("local_lookup_sid: looking up RID %u.\n", (unsigned int)rid)); - if (rid == DOMAIN_USER_RID_ADMIN) { - const char **admin_list = lp_admin_users(-1); - *psid_name_use = SID_NAME_USER; - if (admin_list) { - const char *p = *admin_list; - if(!next_token(&p, name, NULL, sizeof(fstring))) - fstrcpy(name, "Administrator"); - } else { - fstrcpy(name, "Administrator"); - } - return True; - } + /* see if the passdb can help us with the name of the user */ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) { return False; } - - /* see if the passdb can help us with the name of the user */ /* BEING ROOT BLLOCK */ become_root(); diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index 92e2cee7100..4b59b5fdf95 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -514,7 +514,7 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p DEBUG(0,("Can't set flag: %d in set_flags.\n",element)); return False; } - DEBUG(10, ("element %d -> now SET\n", element)); + DEBUG(11, ("element %d -> now SET\n", element)); break; case PDB_DEFAULT: default: diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index ea097c10f69..c8710097525 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -3,6 +3,7 @@ Password and authentication handling Copyright (C) Andrew Bartlett 2002 Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Simo Sorce 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c index 90af10c3736..59ab41b9f67 100644 --- a/source/printing/print_cups.c +++ b/source/printing/print_cups.c @@ -664,7 +664,6 @@ static int cups_job_submit(int snum, struct printjob *pjob) httpClose(http); return ret; - return (ret); } /* @@ -913,6 +912,8 @@ static int cups_queue_get(const char *printer_name, * printer-uri */ + request = ippNew(); + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; request->request.op.request_id = 1; diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c index 5f1d4b622e3..b26083b89e9 100644 --- a/source/rpc_parse/parse_net.c +++ b/source/rpc_parse/parse_net.c @@ -1646,31 +1646,52 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, if(!smb_io_dom_sid2("", &usr->dom_sid, ps, depth)) /* domain SID */ return False; - if (usr->num_other_sids) { + if (usr->buffer_other_sids) { + + uint32 num_other_sids = usr->num_other_sids; + + if (!prs_uint32("num_other_sids", ps, depth, + &num_other_sids)) + return False; + + if (num_other_sids != usr->num_other_sids) + return False; if (UNMARSHALLING(ps)) { usr->other_sids = PRS_ALLOC_MEM(ps, DOM_SID2, usr->num_other_sids); - if (usr->other_sids == NULL) + usr->other_sids_attrib = + PRS_ALLOC_MEM(ps, uint32, usr->num_other_sids); + + if ((num_other_sids != 0) && + ((usr->other_sids == NULL) || + (usr->other_sids_attrib == NULL))) return False; } - - if(!prs_uint32("num_other_groups", ps, depth, &usr->num_other_groups)) - return False; - if (UNMARSHALLING(ps) && usr->num_other_groups > 0) { - usr->other_gids = PRS_ALLOC_MEM(ps, DOM_GID, usr->num_other_groups); - if (usr->other_gids == NULL) + /* First the pointers to the SIDS and attributes */ + + depth++; + + for (i=0; inum_other_sids; i++) { + uint32 ptr = 1; + + if (!prs_uint32("sid_ptr", ps, depth, &ptr)) return False; - } - - for (i = 0; i < usr->num_other_groups; i++) { - if(!smb_io_gid("", &usr->other_gids[i], ps, depth)) /* other GIDs */ + + if (UNMARSHALLING(ps) && (ptr == 0)) + return False; + + if (!prs_uint32("attribute", ps, depth, + &usr->other_sids_attrib[i])) return False; } + for (i = 0; i < usr->num_other_sids; i++) { if(!smb_io_dom_sid2("", &usr->other_sids[i], ps, depth)) /* other domain SIDs */ return False; } + + depth--; } return True; diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 462a6463293..ec52f55b4e3 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -68,31 +68,240 @@ struct generic_mapping usr_generic_mapping = {GENERIC_RIGHTS_USER_READ, GENERIC_ struct generic_mapping grp_generic_mapping = {GENERIC_RIGHTS_GROUP_READ, GENERIC_RIGHTS_GROUP_WRITE, GENERIC_RIGHTS_GROUP_EXECUTE, GENERIC_RIGHTS_GROUP_ALL_ACCESS}; struct generic_mapping ali_generic_mapping = {GENERIC_RIGHTS_ALIAS_READ, GENERIC_RIGHTS_ALIAS_WRITE, GENERIC_RIGHTS_ALIAS_EXECUTE, GENERIC_RIGHTS_ALIAS_ALL_ACCESS}; -static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size); +/******************************************************************* + 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, act_sid, domadmin_sid; + SEC_ACE ace[4]; + SEC_ACCESS mask; + size_t i = 0; + + 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, GENERIC_RIGHTS_DOMAIN_EXECUTE | GENERIC_RIGHTS_DOMAIN_READ); + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + + init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS); + + init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /* add domain admins if we are a DC */ + + if ( IS_DC ) { + sid_copy( &domadmin_sid, get_global_sam_sid() ); + sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); + init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + } + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, 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 **psd, size_t *sd_size, DOM_SID *usr_sid) +{ + extern DOM_SID global_sid_World; + DOM_SID adm_sid, act_sid, domadmin_sid; + size_t i = 0; + + SEC_ACE ace[5]; + 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, GENERIC_RIGHTS_USER_EXECUTE | GENERIC_RIGHTS_USER_READ); + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + + init_sec_access(&mask, GENERIC_RIGHTS_USER_ALL_ACCESS); + init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /* add domain admins if we are a DC */ + + if ( IS_DC ) { + sid_copy( &domadmin_sid, get_global_sam_sid() ); + sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); + init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + } + + /*extended access for the user*/ + + init_sec_access(&mask,READ_CONTROL_ACCESS | SA_RIGHT_USER_CHANGE_PASSWORD | SA_RIGHT_USER_SET_LOC_COM); + init_sec_ace(&ace[i++], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + 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, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + 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, GENERIC_RIGHTS_GROUP_EXECUTE | GENERIC_RIGHTS_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, GENERIC_RIGHTS_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 ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} + +/******************************************************************* + 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, GENERIC_RIGHTS_ALIAS_EXECUTE | GENERIC_RIGHTS_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, GENERIC_RIGHTS_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, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} /******************************************************************* Checks if access to an object should be granted, and returns that level of access for further checks. ********************************************************************/ -static NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_token, uint32 des_access, - uint32 *acc_granted, const char *debug) +static NTSTATUS access_check_samr_object( SEC_DESC *psd, NT_USER_TOKEN *token, + SE_PRIV *rights, uint32 rights_mask, + uint32 des_access, uint32 *acc_granted, + const char *debug ) { NTSTATUS status = NT_STATUS_ACCESS_DENIED; + uint32 saved_mask = 0; - if (!se_access_check(psd, nt_user_token, des_access, acc_granted, &status)) { + /* check privileges; certain SAM access bits should be overridden + by privileges (mostly having to do with creating/modifying/deleting + users and groups) */ + + if ( rights && user_has_any_privilege( token, rights ) ) { + + saved_mask = (des_access & rights_mask); + des_access &= ~saved_mask; + + DEBUG(4,("access_check_samr_object: user rights saved access mask [0x%x]\n", + saved_mask)); + } + + + /* check the security descriptor first */ + + if ( se_access_check(psd, token, des_access, acc_granted, &status) ) + goto done; + + /* give root a free pass */ + + 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")); + *acc_granted = des_access; - 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)); - } + + status = NT_STATUS_OK; + goto done; } + + + DEBUG(2,("%s: ACCESS DENIED (requested: %#010x)\n", debug, des_access)); + +done: + /* add in any bits saved during the privilege check (only + matters is syayus is ok) */ + + *acc_granted |= saved_mask; + return status; } @@ -102,20 +311,29 @@ static NTSTATUS access_check_samr_object(SEC_DESC *psd, NT_USER_TOKEN *nt_user_t static 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(5,("%s: access check ((granted: %#010x; required: %#010x)\n", + debug, acc_granted, acc_required)); + + /* check the security descriptor first */ + + if ( (acc_granted&acc_required) == acc_required ) + return NT_STATUS_OK; + + /* give root a free pass */ + + if (geteuid() == sec_initial_uid()) { + + DEBUG(4,("%s: ACCESS should be DENIED (granted: %#010x; required: %#010x)\n", debug, acc_granted, acc_required)); - return NT_STATUS_ACCESS_DENIED; + DEBUGADD(4,("but overwritten by euid == 0\n")); + + return NT_STATUS_OK; } - return NT_STATUS_OK; + + DEBUG(2,("%s: ACCESS DENIED (granted: %#010x; required: %#010x)\n", + debug, acc_granted, acc_required)); + + return NT_STATUS_ACCESS_DENIED; } @@ -355,281 +573,126 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) return NT_STATUS_OK; } - -/******************************************************************* - _samr_close_hnd - ********************************************************************/ - -NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HND *r_u) -{ - r_u->status = NT_STATUS_OK; - - /* close the policy handle */ - if (!close_policy_hnd(p, &q_u->pol)) - return NT_STATUS_OBJECT_NAME_INVALID; - - DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__)); - - return r_u->status; -} - -/******************************************************************* - samr_reply_open_domain - ********************************************************************/ - -NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u) -{ - 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, (void**)&info)) - return NT_STATUS_INVALID_HANDLE; - - if (!NT_STATUS_IS_OK(status = access_check_samr_function(info->acc_granted, SA_RIGHT_SAM_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)) - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - - DEBUG(5,("samr_open_domain: %d\n", __LINE__)); - - return r_u->status; -} - -/******************************************************************* - _samr_get_usrdom_pwinfo - ********************************************************************/ - -NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, SAMR_R_GET_USRDOM_PWINFO *r_u) -{ - struct samr_info *info = NULL; - - r_u->status = NT_STATUS_OK; - - /* find the policy handle. open a policy on it. */ - if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)&info)) - return NT_STATUS_INVALID_HANDLE; - - if (!sid_check_is_in_our_domain(&info->sid)) - return NT_STATUS_OBJECT_TYPE_MISMATCH; - - init_samr_r_get_usrdom_pwinfo(r_u, NT_STATUS_OK); - - DEBUG(5,("_samr_get_usrdom_pwinfo: %d\n", __LINE__)); - - /* - * NT sometimes return NT_STATUS_ACCESS_DENIED - * I don't know yet why. - */ - - return r_u->status; -} - -/******************************************************************* - 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, act_sid, domadmin_sid; - SEC_ACE ace[4]; - SEC_ACCESS mask; - size_t i = 0; - - 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, GENERIC_RIGHTS_DOMAIN_EXECUTE | GENERIC_RIGHTS_DOMAIN_READ); - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /*full access for builtin aliases Administrators and Account Operators*/ - - init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS); - - init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /* add domain admins if we are a DC */ - - if ( IS_DC ) { - sid_copy( &domadmin_sid, get_global_sam_sid() ); - sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); - init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - } - - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL) - return NT_STATUS_NO_MEMORY; - - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, 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 **psd, size_t *sd_size, DOM_SID *usr_sid) -{ - extern DOM_SID global_sid_World; - DOM_SID adm_sid, act_sid, domadmin_sid; - size_t i = 0; - - SEC_ACE ace[5]; - 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, GENERIC_RIGHTS_USER_EXECUTE | GENERIC_RIGHTS_USER_READ); - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /*full access for builtin aliases Administrators and Account Operators*/ - - init_sec_access(&mask, GENERIC_RIGHTS_USER_ALL_ACCESS); - init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /* add domain admins if we are a DC */ - - if ( IS_DC ) { - sid_copy( &domadmin_sid, get_global_sam_sid() ); - sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); - init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - } - - /*extended access for the user*/ - - init_sec_access(&mask,READ_CONTROL_ACCESS | SA_RIGHT_USER_CHANGE_PASSWORD | SA_RIGHT_USER_SET_LOC_COM); - init_sec_ace(&ace[i++], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - 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, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) - return NT_STATUS_NO_MEMORY; - - return NT_STATUS_OK; -} - + /******************************************************************* - samr_make_grp_obj_sd + _samr_close_hnd ********************************************************************/ -static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +NTSTATUS _samr_close_hnd(pipes_struct *p, SAMR_Q_CLOSE_HND *q_u, SAMR_R_CLOSE_HND *r_u) { - extern DOM_SID global_sid_World; - DOM_SID adm_sid; - DOM_SID act_sid; + r_u->status = NT_STATUS_OK; - SEC_ACE ace[3]; - SEC_ACCESS mask; + /* close the policy handle */ + if (!close_policy_hnd(p, &q_u->pol)) + return NT_STATUS_OBJECT_NAME_INVALID; - SEC_ACL *psa = NULL; + DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__)); - sid_copy(&adm_sid, &global_sid_Builtin); - sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + return r_u->status; +} - sid_copy(&act_sid, &global_sid_Builtin); - sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); +/******************************************************************* + samr_reply_open_domain + ********************************************************************/ - /*basic access for every one*/ - init_sec_access(&mask, GENERIC_RIGHTS_GROUP_EXECUTE | GENERIC_RIGHTS_GROUP_READ); - init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); +NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN_DOMAIN *r_u) +{ + struct samr_info *info; + SEC_DESC *psd = NULL; + uint32 acc_granted; + uint32 des_access = q_u->flags; + size_t sd_size; + NTSTATUS status; + SE_PRIV se_rights; - /*full access for builtin aliases Administrators and Account Operators*/ - init_sec_access(&mask, GENERIC_RIGHTS_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); + r_u->status = NT_STATUS_OK; - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) - return NT_STATUS_NO_MEMORY; + /* find the connection policy handle. */ + + if ( !find_policy_by_hnd(p, &q_u->pol, (void**)&info) ) + return NT_STATUS_INVALID_HANDLE; - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) + status = access_check_samr_function( info->acc_granted, + SA_RIGHT_SAM_OPEN_DOMAIN, "_samr_open_domain" ); + + if ( !NT_STATUS_IS_OK(status) ) + 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 ); + + se_priv_copy( &se_rights, &se_machine_account ); + se_priv_add( &se_rights, &se_add_users ); + + status = access_check_samr_object( psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_DOMAIN_WRITE, des_access, + &acc_granted, "_samr_open_domain" ); + + if ( !NT_STATUS_IS_OK(status) ) + 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; - return NT_STATUS_OK; + /* get a (unique) handle. open a policy on it. */ + if (!create_policy_hnd(p, &r_u->domain_pol, free_samr_info, (void *)info)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + DEBUG(5,("samr_open_domain: %d\n", __LINE__)); + + return r_u->status; } /******************************************************************* - samr_make_ali_obj_sd + _samr_get_usrdom_pwinfo ********************************************************************/ -static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, SAMR_R_GET_USRDOM_PWINFO *r_u) { - extern DOM_SID global_sid_World; - DOM_SID adm_sid; - DOM_SID act_sid; + struct samr_info *info = NULL; - SEC_ACE ace[3]; - SEC_ACCESS mask; + r_u->status = NT_STATUS_OK; - SEC_ACL *psa = NULL; + /* find the policy handle. open a policy on it. */ + if (!find_policy_by_hnd(p, &q_u->user_pol, (void **)&info)) + return NT_STATUS_INVALID_HANDLE; - sid_copy(&adm_sid, &global_sid_Builtin); - sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + if (!sid_check_is_in_our_domain(&info->sid)) + return NT_STATUS_OBJECT_TYPE_MISMATCH; - sid_copy(&act_sid, &global_sid_Builtin); - sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + init_samr_r_get_usrdom_pwinfo(r_u, NT_STATUS_OK); - /*basic access for every one*/ - init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_EXECUTE | GENERIC_RIGHTS_ALIAS_READ); - init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + DEBUG(5,("_samr_get_usrdom_pwinfo: %d\n", __LINE__)); - /*full access for builtin aliases Administrators and Account Operators*/ - init_sec_access(&mask, GENERIC_RIGHTS_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); + /* + * NT sometimes return NT_STATUS_ACCESS_DENIED + * I don't know yet why. + */ - if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) - return NT_STATUS_NO_MEMORY; + return r_u->status; +} - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) - return NT_STATUS_NO_MEMORY; - return NT_STATUS_OK; +/******************************************************************* + _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; } -static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *sid, uint32 *acc_granted) + +/******************************************************************* +********************************************************************/ + +static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol, + DOM_SID *sid, uint32 *acc_granted) { struct samr_info *info = NULL; @@ -646,17 +709,6 @@ static BOOL get_lsa_policy_samr_sid(pipes_struct *p, POLICY_HND *pol, DOM_SID *s } /******************************************************************* - _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 ********************************************************************/ @@ -1646,34 +1698,45 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE size_t sd_size; BOOL ret; NTSTATUS nt_status; + SE_PRIV se_rights; r_u->status = NT_STATUS_OK; /* 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)) + + 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, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_user"))) { + nt_status = access_check_samr_function( acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_user" ); + + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - } nt_status = pdb_init_sam_talloc(p->mem_ctx, &sampass); - if (!NT_STATUS_IS_OK(nt_status)) { + + 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"))) { + + se_priv_copy( &se_rights, &se_machine_account ); + se_priv_add( &se_rights, &se_add_users ); + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, + &acc_granted, "_samr_open_user"); + + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - } become_root(); ret=pdb_getsampwsid(sampass, &sid); @@ -2354,7 +2417,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA se_map_generic(&des_access, &usr_generic_mapping); nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, - des_access, &acc_granted, "_samr_create_user"); + &se_rights, GENERIC_RIGHTS_USER_WRITE, des_access, + &acc_granted, "_samr_create_user"); if ( !NT_STATUS_IS_OK(nt_status) ) { return nt_status; @@ -2452,11 +2516,12 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u 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"))) { + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + NULL, 0, des_access, &acc_granted, "_samr_connect"); + + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - } r_u->status = NT_STATUS_OK; @@ -2502,11 +2567,12 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 * 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"))) { + + nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + NULL, 0, des_access, &acc_granted, "_samr_connect4"); + + if ( !NT_STATUS_IS_OK(nt_status) ) return nt_status; - } r_u->status = NT_STATUS_OK; @@ -2651,29 +2717,40 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A uint32 des_access = q_u->access_mask; size_t sd_size; NTSTATUS status; + SE_PRIV se_rights; r_u->status = NT_STATUS_OK; /* 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)) + + if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted) ) return NT_STATUS_INVALID_HANDLE; + + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_alias"); - if (!NT_STATUS_IS_OK(status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_alias"))) { + if ( !NT_STATUS_IS_OK(status) ) return status; - } /* append the alias' RID to it */ + 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"))) { + + se_priv_add( &se_rights, &se_add_users ); + + + status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_ALIAS_WRITE, des_access, + &acc_granted, "_samr_open_alias"); + + if ( !NT_STATUS_IS_OK(status) ) return status; - } /* * we should check if the rid really exist !!! @@ -2697,20 +2774,8 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A set_user_info_10 ********************************************************************/ -static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid) +static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd =NULL; - BOOL ret; - - pdb_init_sam(&pwd); - - ret = pdb_getsampwsid(pwd, sid); - - if(ret==False) { - pdb_free_sam(&pwd); - return False; - } - if (id10 == NULL) { DEBUG(5, ("set_user_info_10: NULL id10\n")); pdb_free_sam(&pwd); @@ -2737,16 +2802,8 @@ static BOOL set_user_info_10(const SAM_USER_INFO_10 *id10, DOM_SID *sid) set_user_info_12 ********************************************************************/ -static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid) +static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd = NULL; - - pdb_init_sam(&pwd); - - if(!pdb_getsampwsid(pwd, sid)) { - pdb_free_sam(&pwd); - return False; - } if (id12 == NULL) { DEBUG(2, ("set_user_info_12: id12 is NULL\n")); @@ -2816,22 +2873,13 @@ static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass) set_user_info_20 ********************************************************************/ -static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, DOM_SID *sid) +static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd = NULL; - if (id20 == NULL) { DEBUG(5, ("set_user_info_20: NULL id20\n")); return False; } - pdb_init_sam(&pwd); - - if (!pdb_getsampwsid(pwd, sid)) { - pdb_free_sam(&pwd); - return False; - } - copy_id20_to_sam_passwd(pwd, id20); /* write the change out */ @@ -2848,22 +2896,14 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, DOM_SID *sid) set_user_info_21 ********************************************************************/ -static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid) +static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd = NULL; if (id21 == NULL) { DEBUG(5, ("set_user_info_21: NULL id21\n")); return False; } - pdb_init_sam(&pwd); - - if (!pdb_getsampwsid(pwd, sid)) { - pdb_free_sam(&pwd); - return False; - } - copy_id21_to_sam_passwd(pwd, id21); /* @@ -2891,9 +2931,8 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid) set_user_info_23 ********************************************************************/ -static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid) +static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd = NULL; pstring plaintext_buf; uint32 len; uint16 acct_ctrl; @@ -2903,13 +2942,6 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid) return False; } - pdb_init_sam(&pwd); - - if (!pdb_getsampwsid(pwd, sid)) { - pdb_free_sam(&pwd); - return False; - } - DEBUG(5, ("Attempting administrator password change (level 23) for user %s\n", pdb_get_username(pwd))); @@ -2966,20 +2998,12 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid) set_user_info_pw ********************************************************************/ -static BOOL set_user_info_pw(char *pass, DOM_SID *sid) +static BOOL set_user_info_pw(char *pass, SAM_ACCOUNT *pwd) { - SAM_ACCOUNT *pwd = NULL; uint32 len; pstring plaintext_buf; uint16 acct_ctrl; - pdb_init_sam(&pwd); - - if (!pdb_getsampwsid(pwd, sid)) { - pdb_free_sam(&pwd); - return False; - } - DEBUG(5, ("Attempting administrator password change for user %s\n", pdb_get_username(pwd))); @@ -3038,14 +3062,16 @@ static BOOL set_user_info_pw(char *pass, DOM_SID *sid) NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SET_USERINFO *r_u) { + SAM_ACCOUNT *pwd = NULL; 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; - BOOL can_add_machines; - SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; + BOOL ret; + BOOL has_enough_rights; + SE_PRIV se_rights; DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__)); @@ -3076,24 +3102,42 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE DEBUG(5, ("_samr_set_userinfo: NULL info level\n")); return NT_STATUS_INVALID_INFO_CLASS; } + + pdb_init_sam(&pwd); + + become_root(); + ret = pdb_getsampwsid(pwd, &sid); + unbecome_root(); + + if ( !ret ) { + pdb_free_sam(&pwd); + return NT_STATUS_NO_SUCH_USER; + } + + /* deal with machine password changes differently from userinfo changes */ + + if ( pdb_get_acct_ctrl(pwd) & ACB_WSTRUST ) + se_priv_copy( &se_rights, &se_machine_account ); + else + se_priv_copy( &se_rights, &se_add_users ); - /* check to see if we are a domain admin */ + /* check to see if we have the sufficient rights */ - can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); + has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", - p->pipe_user_name, can_add_machines ? "" : " not")); + DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", + p->pipe_user_name, has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ - if ( can_add_machines ) - become_root(); - + if ( has_enough_rights ) + become_root(); + /* ok! user info levels (lots: see MSDEV help), off we go... */ switch (switch_value) { - case 0x12: - if (!set_user_info_12(ctr->info.id12, &sid)) + case 18: + if (!set_user_info_12(ctr->info.id12, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; @@ -3105,7 +3149,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, &sid)) + if (!set_user_info_pw((char *)ctr->info.id24->pass, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; @@ -3141,7 +3185,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, &sid)) + if (!set_user_info_23(ctr->info.id23, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; @@ -3150,7 +3194,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE } - if ( can_add_machines ) + if ( has_enough_rights ) unbecome_root(); /* ================ END SeMachineAccountPrivilege BLOCK ================ */ @@ -3164,14 +3208,16 @@ 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) { + SAM_ACCOUNT *pwd = NULL; DOM_SID sid; 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; - BOOL can_add_machines; - SE_PRIV se_machineop = SE_MACHINE_ACCOUNT; + BOOL ret; + BOOL has_enough_rights; + SE_PRIV se_rights; DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__)); @@ -3195,43 +3241,61 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ switch_value=ctr->switch_value; - /* check to see if we are a domain admin */ + pdb_init_sam(&pwd); + + become_root(); + ret = pdb_getsampwsid(pwd, &sid); + unbecome_root(); + + if ( !ret ) { + pdb_free_sam(&pwd); + return NT_STATUS_NO_SUCH_USER; + } + + /* deal with machine password changes differently from userinfo changes */ + + if ( pdb_get_acct_ctrl(pwd) & ACB_WSTRUST ) + se_priv_copy( &se_rights, &se_machine_account ); + else + se_priv_copy( &se_rights, &se_add_users ); + + /* check to see if we have the sufficient rights */ - can_add_machines = user_has_privileges( p->pipe_user.nt_user_token, &se_machineop ); + has_enough_rights = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); - DEBUG(5, ("_samr_create_user: %s is%s a member of the Domain Admins group\n", - p->pipe_user_name, can_add_machines ? "" : " not")); + DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", + p->pipe_user_name, has_enough_rights ? "" : " not")); /* ================ BEGIN SeMachineAccountPrivilege BLOCK ================ */ - if ( can_add_machines ) - become_root(); - + if ( has_enough_rights ) + become_root(); + /* ok! user info levels (lots: see MSDEV help), off we go... */ switch (switch_value) { case 21: - if (!set_user_info_21(ctr->info.id21, &sid)) + if (!set_user_info_21(ctr->info.id21, pwd)) return NT_STATUS_ACCESS_DENIED; break; case 20: - if (!set_user_info_20(ctr->info.id20, &sid)) + if (!set_user_info_20(ctr->info.id20, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; case 16: - if (!set_user_info_10(ctr->info.id10, &sid)) + if (!set_user_info_10(ctr->info.id10, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; case 18: /* Used by AS/U JRA. */ - if (!set_user_info_12(ctr->info.id12, &sid)) + if (!set_user_info_12(ctr->info.id12, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; default: r_u->status = NT_STATUS_INVALID_INFO_CLASS; } - if ( can_add_machines ) + if ( has_enough_rights ) unbecome_root(); /* ================ END SeMachineAccountPrivilege BLOCK ================ */ @@ -4371,25 +4435,32 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G NTSTATUS status; fstring sid_string; BOOL ret; + SE_PRIV se_rights; 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, SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_group"))) { + status = access_check_samr_function(acc_granted, + SA_RIGHT_DOMAIN_OPEN_ACCOUNT, "_samr_open_group"); + + if ( !NT_STATUS_IS_OK(status) ) 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; - } + se_priv_copy( &se_rights, &se_add_users ); + + status = access_check_samr_object(psd, p->pipe_user.nt_user_token, + &se_rights, GENERIC_RIGHTS_GROUP_WRITE, des_access, + &acc_granted, "_samr_open_group"); + + if ( !NT_STATUS_IS_OK(status) ) + return status; /* this should not be hard-coded like this */ + if (!sid_equal(&sid, get_global_sam_sid())) return NT_STATUS_ACCESS_DENIED; diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c index 7d60749ae2f..597c950a241 100644 --- a/source/rpcclient/cmd_lsarpc.c +++ b/source/rpcclient/cmd_lsarpc.c @@ -278,23 +278,29 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - /* Lookup list of trusted domains */ - - result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, - &num_domains, - &domain_names, &domain_sids); - if (!NT_STATUS_IS_OK(result) && - !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) && - !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) - goto done; - - /* Print results: list of names and sids returned in this response. */ - for (i = 0; i < num_domains; i++) { - fstring sid_str; + result = STATUS_MORE_ENTRIES; + + while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { - sid_to_string(sid_str, &domain_sids[i]); - printf("%s %s\n", domain_names[i] ? domain_names[i] : - "*unknown*", sid_str); + /* Lookup list of trusted domains */ + + result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + &num_domains, + &domain_names, &domain_sids); + if (!NT_STATUS_IS_OK(result) && + !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) && + !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) + goto done; + + /* Print results: list of names and sids returned in this + * response. */ + for (i = 0; i < num_domains; i++) { + fstring sid_str; + + sid_to_string(sid_str, &domain_sids[i]); + printf("%s %s\n", domain_names[i] ? domain_names[i] : + "*unknown*", sid_str); + } } done: diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c index 0b0d015238e..fa77af4145d 100644 --- a/source/rpcclient/cmd_spoolss.c +++ b/source/rpcclient/cmd_spoolss.c @@ -31,6 +31,13 @@ struct table_node { int version; }; +/* The version int is used by getdrivers. Note that + all architecture strings that support mutliple + versions must be grouped together since enumdrivers + uses this property to prevent issuing multiple + enumdriver calls for the same arch */ + + static const struct table_node archi_table[]= { {"Windows 4.0", "WIN40", 0 }, @@ -1134,6 +1141,11 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, { uint32 needed; + /* check to see if we already asked for this architecture string */ + + if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) ) + continue; + werror = cli_spoolss_enumprinterdrivers( cli, mem_ctx, 0, &needed, info_level, archi_table[i].long_archi, &returned, &ctr); diff --git a/source/smbd/open.c b/source/smbd/open.c index bf3fbf7fecd..70632a20eb7 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -665,7 +665,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); - opb_ret = request_oplock_break(share_entry, False); + opb_ret = request_oplock_break(share_entry); /* Now relock. */ lock_share_entry(conn, dev, inode); diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c index 3ebf93e5608..a55d5443d56 100644 --- a/source/smbd/oplock.c +++ b/source/smbd/oplock.c @@ -598,13 +598,13 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un /**************************************************************************** Process a level II oplock break directly. + We must call this function with the share mode entry locked. ****************************************************************************/ -BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) +static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) { extern uint32 global_client_caps; char outbuf[128]; - BOOL got_lock = False; SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; @@ -644,25 +644,16 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /* * Now we must update the shared memory structure to tell * everyone else we no longer have a level II oplock on - * this open file. If local_request is true then token is - * the existing lock on the shared memory area. + * this open file. We must call this function with the share mode + * entry locked so we can change the entry directly. */ - if(!local_request && lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("oplock_break_level2: unable to lock share entry for file %s\n", fsp->fsp_name )); - } else { - got_lock = True; - } - if(remove_share_oplock(fsp)==False) { DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); } release_file_oplock(fsp); - if (!local_request && got_lock) - unlock_share_entry_fsp(fsp); - if(level_II_oplocks_open < 0) { DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", level_II_oplocks_open)); @@ -680,6 +671,7 @@ BOOL oplock_break_level2(files_struct *fsp, BOOL local_request, int token) /**************************************************************************** Process an oplock break directly. + This is always called with the share mode lock *NOT* held. ****************************************************************************/ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) @@ -708,8 +700,18 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * Deal with a level II oplock going break to none separately. */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) - return oplock_break_level2(fsp, local_request, -1); + if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + BOOL ret; + /* We must always call oplock_break_level2() with + the share mode entry locked. */ + if (lock_share_entry_fsp(fsp) == False) { + DEBUG(0,("oplock_break: unable to lock share entry for file %s\n", fsp->fsp_name )); + return False; + } + ret = oplock_break_level2(fsp, local_request); + unlock_share_entry_fsp(fsp); + return ret; + } /* Mark the oplock break as sent - we don't want to send twice! */ if (fsp->sent_oplock_break) { @@ -942,11 +944,12 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } /**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. + Send an oplock break message to another smbd process. If the oplock is held + by the local smbd then call the oplock break function directly. + This function is called with no share locks held. ****************************************************************************/ -BOOL request_oplock_break(share_mode_entry *share_entry, BOOL async) +BOOL request_oplock_break(share_mode_entry *share_entry) { char op_break_msg[OPLOCK_BREAK_MSG_LEN]; struct sockaddr_in addr_out; @@ -987,7 +990,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - break_cmd_type = async ? ASYNC_LEVEL_II_OPLOCK_BREAK_CMD : LEVEL_II_OPLOCK_BREAK_CMD; + break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD; } else { break_cmd_type = OPLOCK_BREAK_CMD; } @@ -1005,7 +1008,7 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", addr_out.sin_family = AF_INET; if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a %s oplock break message to ", async ? "asynchronous" : "synchronous" ); + dbgtext( "request_oplock_break: sending a synchronous oplock break message to " ); dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); @@ -1025,16 +1028,6 @@ dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", } /* - * If we just sent a message to a level II oplock share entry in async mode then - * we are done and may return. - */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type) && async) { - DEBUG(3,("request_oplock_break: sent async break message to level II entry.\n")); - return True; - } - - /* * Now we must await the oplock broken message coming back * from the target smbd process. Timeout if it fails to * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. @@ -1147,6 +1140,57 @@ BOOL attempt_close_oplocked_file(files_struct *fsp) } /**************************************************************************** + Send an asynchronous oplock break message to another smbd process. +****************************************************************************/ + +static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry) +{ + char op_break_msg[OPLOCK_BREAK_MSG_LEN]; + struct sockaddr_in addr_out; + pid_t pid = sys_getpid(); + SMB_DEV_T dev = share_entry->dev; + SMB_INO_T inode = share_entry->inode; + unsigned long file_id = share_entry->share_file_id; + + /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */ + + SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD); + memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); + memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); + memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); + memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); + + /* Set the address and port. */ + memset((char *)&addr_out,'\0',sizeof(addr_out)); + addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr_out.sin_port = htons( share_entry->op_port ); + addr_out.sin_family = AF_INET; + + if( DEBUGLVL( 3 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to "); + dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + } + + if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, + (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " ); + dbgtext( "break message to pid %d ", (int)share_entry->pid ); + dbgtext( "on port %d ", share_entry->op_port ); + dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", + (unsigned int)dev, (double)inode, file_id ); + dbgtext( "Error was %s\n", strerror(errno) ); + } + return False; + } + + DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n")); + return True; +} + +/**************************************************************************** This function is called on any file modification or lock request. If a file is level 2 oplocked then it must tell all other level 2 holders to break to none. ****************************************************************************/ @@ -1155,7 +1199,6 @@ void release_level_2_oplocks_on_change(files_struct *fsp) { share_mode_entry *share_list = NULL; pid_t pid = sys_getpid(); - int token = -1; int num_share_modes = 0; int i; @@ -1222,7 +1265,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n")); - oplock_break_level2(new_fsp, True, token); + oplock_break_level2(new_fsp, True); } else { @@ -1232,7 +1275,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp) */ DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); - request_oplock_break(share_entry, True); + request_remote_level2_async_oplock_break(share_entry); } } diff --git a/source/utils/net_help.c b/source/utils/net_help.c index 328e1344591..60206429b7e 100644 --- a/source/utils/net_help.c +++ b/source/utils/net_help.c @@ -132,7 +132,7 @@ int net_help_share(int argc, const char **argv) "[misc. options] [targets]" "\n\tshows a list of all shares together with all users allowed to" "\n\taccess them. This needs the output of 'net usersidlist' on" - "\n\tstdin or in .\n" + "\n\tstdin or in .\n\n" "net [] share MIGRATE FILES [misc. options] [targets]" "\n\tMigrates files from remote to local server\n\n" "net [] share MIGRATE SHARES [misc. options] [targets]" diff --git a/source/utils/net_idmap.c b/source/utils/net_idmap.c index f7ebd94f346..7abb31ab3d9 100644 --- a/source/utils/net_idmap.c +++ b/source/utils/net_idmap.c @@ -288,7 +288,7 @@ static int net_idmap_delete(int argc, const char **argv) int net_help_idmap(int argc, const char **argv) { - d_printf("net idmap dump filename"\ + d_printf("net idmap dump "\ "\n Dump current id mapping\n"); d_printf("net idmap restore"\ diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index 430649d81bb..76b53d61136 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -404,7 +404,7 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, TALLOC_CTX *ctx = talloc_init("rpc_info_internals"); d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain)); d_printf("Domain SID: %s\n", sid_str); - d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num); + d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num.low); d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs); d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps); d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps); @@ -1428,7 +1428,7 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, ALIAS_INFO_CTR alias_info; if (argc != 1) { - d_printf("Group name must be specified\n"); + d_printf("Alias name must be specified\n"); rpc_group_usage(argc, argv); return NT_STATUS_OK; } @@ -1465,9 +1465,9 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, done: if (NT_STATUS_IS_OK(result)) - DEBUG(5, ("add group succeeded\n")); + DEBUG(5, ("add alias succeeded\n")); else - d_printf("add group failed: %s\n", nt_errstr(result)); + d_printf("add alias failed: %s\n", nt_errstr(result)); return result; } -- 2.11.4.GIT