r4852: merge simo changes to srv_srvsvc_nt.c from trunk
[ira/wip.git] / source3 / rpc_server / srv_srvsvc_nt.c
index 69945b50b8485b6823c7d63975349f094be3ffa6..529b4c198d210078d05d8f7c2f7e1195e5bdc2fe 100644 (file)
@@ -27,8 +27,6 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-extern pstring global_myname;
-
 /*******************************************************************
  Utility function to get the 'type' of a share from an snum.
  ********************************************************************/
@@ -130,7 +128,7 @@ static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
 BOOL share_info_db_init(void)
 {
        static pid_t local_pid;
-       char *vstring = "INFO/version";
+       const char *vstring = "INFO/version";
        int32 vers_id;
  
        if (share_tdb && local_pid == sys_getpid())
@@ -145,7 +143,7 @@ BOOL share_info_db_init(void)
        local_pid = sys_getpid();
  
        /* handle a Samba upgrade */
-       tdb_lock_bystring(share_tdb, vstring);
+       tdb_lock_bystring(share_tdb, vstring, 0);
 
        /* Cope with byte-reversed older versions of the db. */
        vers_id = tdb_fetch_int32(share_tdb, vstring);
@@ -186,7 +184,7 @@ static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *
        init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
 
        if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
-               psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, psize);
+               psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
        }
 
        if (!psd) {
@@ -239,7 +237,7 @@ static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC
        fstring key;
        BOOL ret = False;
 
-       mem_ctx = talloc_init();
+       mem_ctx = talloc_init("set_share_security");
        if (mem_ctx == NULL)
                return False;
 
@@ -329,7 +327,7 @@ BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, u
        NT_USER_TOKEN *token = NULL;
        BOOL ret = True;
 
-       mem_ctx = talloc_init();
+       mem_ctx = talloc_init("share_access_check");
        if (mem_ctx == NULL)
                return False;
 
@@ -358,15 +356,12 @@ out:
 
 static void init_srv_share_info_501(pipes_struct *p, SRV_SHARE_INFO_501 *sh501, int snum)
 {
-       int len_net_name;
        pstring remark;
 
-       char *net_name = lp_servicename(snum);
+       const char *net_name = lp_servicename(snum);
        pstrcpy(remark, lp_comment(snum));
        standard_sub_conn(p->conn, remark, sizeof(remark));
 
-       len_net_name = strlen(net_name);
-
        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);
 }
@@ -377,7 +372,6 @@ 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)
 {
-       int len_net_name;
        pstring net_name;
        pstring remark;
        pstring path;
@@ -403,7 +397,6 @@ static void init_srv_share_info_502(pipes_struct *p, SRV_SHARE_INFO_502 *sh502,
        string_replace(path, '/', '\\');
 
        pstrcpy(passwd, "");
-       len_net_name = strlen(net_name);
 
        sd = get_share_security(ctx, snum, &sd_size);
 
@@ -434,10 +427,13 @@ static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh100
 
 static void init_srv_share_info_1005(pipes_struct *p, SRV_SHARE_INFO_1005* sh1005, int snum)
 {
-       sh1005->dfs_root_flag = 0;
+       sh1005->share_info_flags = 0;
 
        if(lp_host_msdfs() && lp_msdfs_root(snum))
-               sh1005->dfs_root_flag = 3;
+               sh1005->share_info_flags |= 
+                       SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT;
+       sh1005->share_info_flags |= 
+               lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT;
 }
 /***************************************************************************
  Fill in a share info level 1006 structure.
@@ -486,10 +482,9 @@ static void init_srv_share_info_1501(pipes_struct *p, SRV_SHARE_INFO_1501 *sh150
 
 static BOOL is_hidden_share(int snum)
 {
-       pstring net_name;
+       const char *net_name = lp_servicename(snum);
 
-       pstrcpy(net_name, lp_servicename(snum));
-       return (net_name[strlen(net_name)] == '$') ? True : False;
+       return (net_name[strlen(net_name) - 1] == '$') ? True : False;
 }
 
 /*******************************************************************
@@ -527,10 +522,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
        switch (info_level) {
        case 0:
        {
-               SRV_SHARE_INFO_0 *info0;
+               SRV_SHARE_INFO_0 *info0 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_0, num_entries);
                int i = 0;
 
-               info0 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_0));
+               if (!info0) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -545,10 +542,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 1:
        {
-               SRV_SHARE_INFO_1 *info1;
+               SRV_SHARE_INFO_1 *info1 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1, num_entries);
                int i = 0;
 
-               info1 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1));
+               if (!info1) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -562,10 +561,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 2:
        {
-               SRV_SHARE_INFO_2 *info2;
+               SRV_SHARE_INFO_2 *info2 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_2, num_entries);
                int i = 0;
 
-               info2 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_2));
+               if (!info2) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -579,10 +580,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 501:
        {
-               SRV_SHARE_INFO_501 *info501;
+               SRV_SHARE_INFO_501 *info501 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_501, num_entries);
                int i = 0;
        
-               info501 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_501));
+               if (!info501) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -596,10 +599,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 502:
        {
-               SRV_SHARE_INFO_502 *info502;
+               SRV_SHARE_INFO_502 *info502 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_502, num_entries);
                int i = 0;
 
-               info502 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_502));
+               if (!info502) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -615,10 +620,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
        
        case 1004:
        {
-               SRV_SHARE_INFO_1004 *info1004;
+               SRV_SHARE_INFO_1004 *info1004 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1004, num_entries);
                int i = 0;
 
-               info1004 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1004));
+               if (!info1004) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -632,10 +639,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 1005:
        {
-               SRV_SHARE_INFO_1005 *info1005;
+               SRV_SHARE_INFO_1005 *info1005 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1005, num_entries);
                int i = 0;
 
-               info1005 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1005));
+               if (!info1005) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -649,10 +658,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 1006:
        {
-               SRV_SHARE_INFO_1006 *info1006;
+               SRV_SHARE_INFO_1006 *info1006 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1006, num_entries);
                int i = 0;
 
-               info1006 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1006));
+               if (!info1006) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -666,10 +677,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 1007:
        {
-               SRV_SHARE_INFO_1007 *info1007;
+               SRV_SHARE_INFO_1007 *info1007 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1007, num_entries);
                int i = 0;
 
-               info1007 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1007));
+               if (!info1007) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -683,10 +696,12 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
 
        case 1501:
        {
-               SRV_SHARE_INFO_1501 *info1501;
+               SRV_SHARE_INFO_1501 *info1501 = TALLOC_ARRAY(ctx, SRV_SHARE_INFO_1501, num_entries);
                int i = 0;
 
-               info1501 = talloc(ctx, num_entries * sizeof(SRV_SHARE_INFO_1501));
+               if (!info1501) {
+                       return False;
+               }
 
                for (snum = *resume_hnd; snum < num_services; snum++) {
                        if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
@@ -1010,7 +1025,7 @@ static void init_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *sto
 static void init_srv_conn_1_info(CONN_INFO_1 *se1, CONN_INFO_1_STR *str1,
                                uint32 id, uint32 type,
                                uint32 num_opens, uint32 num_users, uint32 open_time,
-                               char *usr_name, char *net_name)
+                               const char *usr_name, const char *net_name)
 {
        init_srv_conn_info1(se1 , id, type, num_opens, num_users, open_time, usr_name, net_name);
        init_srv_conn_info1_str(str1, usr_name, net_name);
@@ -1137,8 +1152,7 @@ static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
                int i;
                if (*total_entries > 0) {
                        ctr->ptr_entries = 1;
-                       ctr->file.info3 = talloc(ctx, ctr->num_entries * 
-                                                sizeof(SRV_FILE_INFO_3));
+                       ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries);
                }
                for (i=0 ;i<ctr->num_entries;i++) {
                        init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user");
@@ -1189,7 +1203,7 @@ net server get info
 WERROR _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R_NET_SRV_GET_INFO *r_u)
 {
        WERROR status = WERR_OK;
-       SRV_INFO_CTR *ctr = (SRV_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_INFO_CTR));
+       SRV_INFO_CTR *ctr = TALLOC_P(p->mem_ctx, SRV_INFO_CTR);
 
        if (!ctr)
                return WERR_NOMEM;
@@ -1211,7 +1225,7 @@ WERROR _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R
 
        case 102:
                init_srv_info_102(&ctr->srv.sv102,
-                                 500, global_myname, 
+                                 500, global_myname()
                                  string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
                                  lp_major_announce_version(), lp_minor_announce_version(),
                                  lp_default_server_announce(),
@@ -1225,13 +1239,13 @@ WERROR _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R
                break;
        case 101:
                init_srv_info_101(&ctr->srv.sv101,
-                                 500, global_myname,
+                                 500, global_myname(),
                                  lp_major_announce_version(), lp_minor_announce_version(),
                                  lp_default_server_announce(),
                                  string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
                break;
        case 100:
-               init_srv_info_100(&ctr->srv.sv100, 500, global_myname);
+               init_srv_info_100(&ctr->srv.sv100, 500, global_myname());
                break;
        default:
                status = WERR_UNKNOWN_LEVEL;
@@ -1292,7 +1306,7 @@ WERROR _srv_net_conn_enum(pipes_struct *p, SRV_Q_NET_CONN_ENUM *q_u, SRV_R_NET_C
 {
        DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
 
-       r_u->ctr = (SRV_CONN_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_CONN_INFO_CTR));
+       r_u->ctr = TALLOC_P(p->mem_ctx, SRV_CONN_INFO_CTR);
        if (!r_u->ctr)
                return WERR_NOMEM;
 
@@ -1317,7 +1331,7 @@ WERROR _srv_net_sess_enum(pipes_struct *p, SRV_Q_NET_SESS_ENUM *q_u, SRV_R_NET_S
 {
        DEBUG(5,("_srv_net_sess_enum: %d\n", __LINE__));
 
-       r_u->ctr = (SRV_SESS_INFO_CTR *)talloc(p->mem_ctx, sizeof(SRV_SESS_INFO_CTR));
+       r_u->ctr = TALLOC_P(p->mem_ctx, SRV_SESS_INFO_CTR);
        if (!r_u->ctr)
                return WERR_NOMEM;
 
@@ -1405,10 +1419,7 @@ WERROR _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, S
 
 static char *valid_share_pathname(char *dos_pathname)
 {
-       pstring saved_pathname;
-       pstring unix_pathname;
        char *ptr;
-       int ret;
 
        /* Convert any '\' paths to '/' */
        unix_format(dos_pathname);
@@ -1423,21 +1434,7 @@ static char *valid_share_pathname(char *dos_pathname)
        if (*ptr != '/')
                return NULL;
 
-       /* Can we cd to it ? */
-
-       /* First save our current directory. */
-       if (getcwd(saved_pathname, sizeof(saved_pathname)) == NULL)
-               return False;
-
-       pstrcpy(unix_pathname, ptr);
-       
-       ret = chdir(unix_pathname);
-
-       /* We *MUST* be able to chdir back. Abort if we can't. */
-       if (chdir(saved_pathname) == -1)
-               smb_panic("valid_share_pathname: Unable to restore current directory.\n");
-
-       return (ret != -1) ? ptr : NULL;
+       return ptr;
 }
 
 /*******************************************************************
@@ -1454,8 +1451,10 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
        int type;
        int snum;
        int ret;
-       char *ptr;
+       char *path;
        SEC_DESC *psd = NULL;
+       SE_PRIV se_diskop = SE_DISK_OPERATOR;
+       BOOL is_disk_op;
 
        DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
 
@@ -1478,12 +1477,16 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
 
        get_current_user(&user,p);
 
-       if (user.uid != sec_initial_uid())
+       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.uid != sec_initial_uid() && !is_disk_op )
                return WERR_ACCESS_DENIED;
 
        switch (q_u->info_level) {
        case 1:
-               fstrcpy(pathname, lp_pathname(snum));
+               pstrcpy(pathname, lp_pathname(snum));
                unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(comment));
                type = q_u->info.share.info2.info_2.type;
                psd = NULL;
@@ -1510,17 +1513,30 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
                map_generic_share_sd_bits(psd);
                break;
        case 1004:
-               fstrcpy(pathname, lp_pathname(snum));
+               pstrcpy(pathname, lp_pathname(snum));
                unistr2_to_ascii(comment, &q_u->info.share.info1004.info_1004_str.uni_remark, sizeof(comment));
                type = STYPE_DISKTREE;
                break;
        case 1005:
+                /* XP re-sets the csc policy even if it wasn't changed by the
+                  user, so we must compare it to see if it's what is set in
+                  smb.conf, so that we can contine other ops like setting
+                  ACLs on a share */
+               if (((q_u->info.share.info1005.share_info_flags &
+                     SHARE_1005_CSC_POLICY_MASK) >>
+                    SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum))
+                       return WERR_OK;
+               else {
+                       DEBUG(3, ("_srv_net_share_set_info: client is trying to change csc policy from the network; must be done with smb.conf\n"));
+                       return WERR_ACCESS_DENIED;
+               }
+               break;
        case 1006:
        case 1007:
                return WERR_ACCESS_DENIED;
                break;
        case 1501:
-               fstrcpy(pathname, lp_pathname(snum));
+               pstrcpy(pathname, lp_pathname(snum));
                fstrcpy(comment, lp_comment(snum));
                psd = q_u->info.share.info1501.sdb->sec;
                map_generic_share_sd_bits(psd);
@@ -1536,35 +1552,48 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
                return WERR_ACCESS_DENIED;
                
        /* Check if the pathname is valid. */
-       if (!(ptr = valid_share_pathname( pathname )))
+       if (!(path = valid_share_pathname( pathname )))
                return WERR_OBJECT_PATH_INVALID;
 
        /* Ensure share name, pathname and comment don't contain '"' characters. */
        string_replace(share_name, '"', ' ');
-       string_replace(ptr, '"', ' ');
+       string_replace(path, '"', ' ');
        string_replace(comment, '"', ' ');
 
        DEBUG(10,("_srv_net_share_set_info: change share command = %s\n",
                lp_change_share_cmd() ? lp_change_share_cmd() : "NULL" ));
 
        /* Only call modify function if something changed. */
-
-       if (strcmp(ptr, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) {
-               if (!lp_change_share_cmd() || !*lp_change_share_cmd())
+       
+       if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) 
+       {
+               if (!lp_change_share_cmd() || !*lp_change_share_cmd()) 
                        return WERR_ACCESS_DENIED;
 
                slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-                               lp_change_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment);
+                               lp_change_share_cmd(), dyn_CONFIGFILE, share_name, path, comment);
 
                DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command ));
-               if ((ret = smbrun(command, NULL)) != 0) {
-                       DEBUG(0,("_srv_net_share_set_info: Running [%s] returned (%d)\n", command, ret ));
+                               
+               /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
+       
+               if ( is_disk_op )
+                       become_root();
+                       
+               ret = smbrun(command, NULL);
+               
+               if ( is_disk_op )
+                       unbecome_root();
+                       
+               /********* END SeDiskOperatorPrivilege BLOCK *********/
+
+               DEBUG(3,("_srv_net_share_set_info: Running [%s] returned (%d)\n", command, ret ));              
+       
+               if ( ret != 0 )
                        return WERR_ACCESS_DENIED;
-               }
 
                /* Tell everyone we updated smb.conf. */
                message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-
        } else {
                DEBUG(10,("_srv_net_share_set_info: No change to share name (%s)\n", share_name ));
        }
@@ -1582,7 +1611,7 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
                                        share_name ));
                }
        }
-
+                       
        DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
 
        return WERR_OK;
@@ -1602,8 +1631,10 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
        int type;
        int snum;
        int ret;
-       char *ptr;
+       char *path;
        SEC_DESC *psd = NULL;
+       SE_PRIV se_diskop = SE_DISK_OPERATOR;
+       BOOL is_disk_op;
 
        DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
 
@@ -1611,16 +1642,16 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
 
        get_current_user(&user,p);
 
-       if (user.uid != sec_initial_uid()) {
-               DEBUG(10,("_srv_net_share_add: uid != sec_initial_uid(). Access denied.\n"));
+       is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
+
+       if (user.uid != sec_initial_uid()  && !is_disk_op ) 
                return WERR_ACCESS_DENIED;
-       }
 
        if (!lp_add_share_cmd() || !*lp_add_share_cmd()) {
                DEBUG(10,("_srv_net_share_add: No add share command\n"));
                return WERR_ACCESS_DENIED;
        }
-
+       
        switch (q_u->info_level) {
        case 0:
                /* No path. Not enough info in a level 0 to do anything. */
@@ -1676,32 +1707,45 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
                return WERR_ACCESS_DENIED;
                
        /* Check if the pathname is valid. */
-       if (!(ptr = valid_share_pathname( pathname )))
+       if (!(path = valid_share_pathname( pathname )))
                return WERR_OBJECT_PATH_INVALID;
 
        /* Ensure share name, pathname and comment don't contain '"' characters. */
        string_replace(share_name, '"', ' ');
-       string_replace(ptr, '"', ' ');
+       string_replace(path, '"', ' ');
        string_replace(comment, '"', ' ');
 
        slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-                       lp_add_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment);
-
+                       lp_add_share_cmd(), dyn_CONFIGFILE, share_name, path, comment);
+                       
        DEBUG(10,("_srv_net_share_add: Running [%s]\n", command ));
-       if ((ret = smbrun(command, NULL)) != 0) {
-               DEBUG(0,("_srv_net_share_add: Running [%s] returned (%d)\n", command, ret ));
-               return WERR_ACCESS_DENIED;
-       }
+       
+       /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
+       
+       if ( is_disk_op )
+               become_root();
 
-       if (psd) {
-               if (!set_share_security(p->mem_ctx, share_name, psd))
-                       DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n",
-                               share_name ));
-       }
+       ret = smbrun(command, NULL);
+
+       if ( is_disk_op )
+               unbecome_root();
+               
+       /********* END SeDiskOperatorPrivilege BLOCK *********/
+
+       DEBUG(3,("_srv_net_share_add: Running [%s] returned (%d)\n", command, ret ));
+
+       if ( ret != 0 )
+               return WERR_ACCESS_DENIED;
 
        /* Tell everyone we updated smb.conf. */
        message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
 
+       if (psd) {
+               if (!set_share_security(p->mem_ctx, share_name, psd)) {
+                       DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n", share_name ));
+               }
+       }
+
        /*
         * We don't call reload_services() here, the message will
         * cause this to be done before the next packet is read
@@ -1725,6 +1769,8 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
        fstring share_name;
        int ret;
        int snum;
+       SE_PRIV se_diskop = SE_DISK_OPERATOR;
+       BOOL is_disk_op;
 
        DEBUG(5,("_srv_net_share_del: %d\n", __LINE__));
 
@@ -1744,27 +1790,42 @@ WERROR _srv_net_share_del(pipes_struct *p, SRV_Q_NET_SHARE_DEL *q_u, SRV_R_NET_S
 
        get_current_user(&user,p);
 
-       if (user.uid != sec_initial_uid())
+       is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
+
+       if (user.uid != sec_initial_uid()  && !is_disk_op ) 
                return WERR_ACCESS_DENIED;
 
        if (!lp_delete_share_cmd() || !*lp_delete_share_cmd())
                return WERR_ACCESS_DENIED;
-
+               
        slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
                        lp_delete_share_cmd(), dyn_CONFIGFILE, lp_servicename(snum));
 
        DEBUG(10,("_srv_net_share_del: Running [%s]\n", command ));
-       if ((ret = smbrun(command, NULL)) != 0) {
-               DEBUG(0,("_srv_net_share_del: Running [%s] returned (%d)\n", command, ret ));
-               return WERR_ACCESS_DENIED;
-       }
 
-       /* Delete the SD in the database. */
-       delete_share_security(snum);
+       /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
+       
+       if ( is_disk_op )
+               become_root();
+
+       ret = smbrun(command, NULL);
+
+       if ( is_disk_op )
+               unbecome_root();
+               
+       /********* END SeDiskOperatorPrivilege BLOCK *********/
+
+       DEBUG(3,("_srv_net_share_del: Running [%s] returned (%d)\n", command, ret ));
+
+       if ( ret != 0 )
+               return WERR_ACCESS_DENIED;
 
        /* Tell everyone we updated smb.conf. */
        message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
 
+       /* Delete the SD in the database. */
+       delete_share_security(snum);
+
        lp_killservice(snum);
 
        return WERR_OK;
@@ -1787,7 +1848,7 @@ WERROR _srv_net_remote_tod(pipes_struct *p, SRV_Q_NET_REMOTE_TOD *q_u, SRV_R_NET
        struct tm *t;
        time_t unixdate = time(NULL);
 
-       tod = (TIME_OF_DAY_INFO *)talloc(p->mem_ctx, sizeof(TIME_OF_DAY_INFO));
+       tod = TALLOC_P(p->mem_ctx, TIME_OF_DAY_INFO);
        if (!tod)
                return WERR_NOMEM;
 
@@ -1869,18 +1930,31 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
                r_u->status = WERR_ACCESS_DENIED;
                goto error_exit;
        }
-    became_user = True;
+       became_user = True;
 
        unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
        unix_convert(filename, conn, NULL, &bad_path, &st);
-       fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDONLY),
-                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
+       if (bad_path) {
+               DEBUG(3,("_srv_net_file_query_secdesc: bad pathname %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       if (!check_name(filename,conn)) {
+               DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
+                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
+                               &access_mode, &action);
 
        if (!fsp) {
                /* Perhaps it is a directory */
                if (errno == EISDIR)
                        fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
-                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
+                                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
@@ -1889,7 +1963,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
                }
        }
 
-       sd_size = conn->vfs_ops.get_nt_acl(fsp, fsp->fsp_name, &psd);
+       sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
 
        if (sd_size == 0) {
                DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", filename));
@@ -1976,15 +2050,28 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
 
        unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
        unix_convert(filename, conn, NULL, &bad_path, &st);
+       if (bad_path) {
+               DEBUG(3,("_srv_net_file_set_secdesc: bad pathname %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
+
+       if (!check_name(filename,conn)) {
+               DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", filename));
+               r_u->status = WERR_ACCESS_DENIED;
+               goto error_exit;
+       }
 
-       fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDWR),
-                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
+
+       fsp = open_file_shared(conn, filename, &st, SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDWR),
+                       (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, INTERNAL_OPEN_ONLY,
+                       &access_mode, &action);
 
        if (!fsp) {
                /* Perhaps it is a directory */
                if (errno == EISDIR)
                        fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
-                                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
+                                               (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
@@ -1993,7 +2080,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
                }
        }
 
-       ret = conn->vfs_ops.set_nt_acl(fsp, fsp->fsp_name, q_u->sec_info, q_u->sec_desc);
+       ret = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, q_u->sec_info, q_u->sec_desc);
 
        if (ret == False) {
                DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", filename));
@@ -2080,16 +2167,8 @@ WERROR _srv_net_disk_enum(pipes_struct *p, SRV_Q_NET_DISK_ENUM *q_u, SRV_R_NET_D
 
        r_u->disk_enum_ctr.unknown = 0; 
 
-       {
-               DISK_INFO *dinfo;
-
-               int dinfo_size = MAX_SERVER_DISK_ENTRIES * sizeof(*dinfo);
-         
-               if(!(dinfo =  talloc(ctx, dinfo_size))) {
-                       return WERR_NOMEM;
-               }
-
-               r_u->disk_enum_ctr.disk_info = dinfo;
+       if(!(r_u->disk_enum_ctr.disk_info =  TALLOC_ARRAY(ctx, DISK_INFO, MAX_SERVER_DISK_ENTRIES))) {
+               return WERR_NOMEM;
        }
 
        r_u->disk_enum_ctr.disk_info_ptr = r_u->disk_enum_ctr.disk_info ? 1 : 0;