r10656: BIG merge from trunk. Features not copied over
[vlendec/samba-autobuild/.git] / source3 / rpc_server / srv_srvsvc_nt.c
index 087c50451e5d5c42ca597df0f2c346b667d9d042..9643b2a72498711c33ae7a868057c372e78eea70 100644 (file)
@@ -24,6 +24,8 @@
 
 #include "includes.h"
 
+extern struct generic_mapping file_generic_mapping;
+
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
@@ -111,7 +113,8 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
  What to do when smb.conf is updated.
  ********************************************************************/
 
-static void smb_conf_updated(int msg_type, pid_t src, void *buf, size_t len)
+static void smb_conf_updated(int msg_type, struct process_id src,
+                            void *buf, size_t len)
 {
        DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
        reload_services(False);
@@ -170,8 +173,6 @@ BOOL share_info_db_init(void)
 
 static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *psize)
 {
-       extern DOM_SID global_sid_World;
-       extern struct generic_mapping file_generic_mapping;
        SEC_ACCESS sa;
        SEC_ACE ace;
        SEC_ACL *psa = NULL;
@@ -293,7 +294,6 @@ static BOOL delete_share_security(int snum)
 
 void map_generic_share_sd_bits(SEC_DESC *psd)
 {
-       extern struct generic_mapping file_generic_mapping;
        int i;
        SEC_ACL *ps_dacl = NULL;
 
@@ -356,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);
 }
@@ -375,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;
@@ -401,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);
 
@@ -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)) ) {
@@ -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;
@@ -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;
 
@@ -1334,6 +1348,70 @@ WERROR _srv_net_sess_enum(pipes_struct *p, SRV_Q_NET_SESS_ENUM *q_u, SRV_R_NET_S
        return r_u->status;
 }
 
+/*******************************************************************
+net sess del
+********************************************************************/
+
+WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u)
+{
+       struct sessionid *session_list;
+       struct current_user user;
+       int num_sessions, snum;
+       fstring username;
+       fstring machine;
+       BOOL not_root = False;
+
+       rpcstr_pull_unistr2_fstring(username, &q_u->uni_user_name);
+       rpcstr_pull_unistr2_fstring(machine, &q_u->uni_cli_name);
+
+       /* strip leading backslashes if any */
+       while (machine[0] == '\\') {
+               memmove(machine, &machine[1], strlen(machine));
+       }
+
+       num_sessions = list_sessions(&session_list);
+
+       DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
+
+       r_u->status = WERR_ACCESS_DENIED;
+
+       get_current_user(&user, p);
+
+       /* fail out now if you are not root or not a domain admin */
+
+       if ((user.uid != sec_initial_uid()) && 
+               ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) {
+
+               goto done;
+       }
+
+       for (snum = 0; snum < num_sessions; snum++) {
+
+               if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) &&
+                   strequal(session_list[snum].remote_machine, machine)) {
+               
+                       if (user.uid != sec_initial_uid()) {
+                               not_root = True;
+                               become_root();
+                       }
+
+                       if (message_send_pid(pid_to_procid(session_list[snum].pid), MSG_SHUTDOWN, NULL, 0, False))
+                               r_u->status = WERR_OK;
+
+                       if (not_root) 
+                               unbecome_root();
+               }
+       }
+
+       DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__));
+
+
+done:
+       SAFE_FREE(session_list);
+
+       return r_u->status;
+}
+
 /*******************************************************************
  Net share enum all.
 ********************************************************************/
@@ -1403,12 +1481,9 @@ WERROR _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, S
  Check a given DOS pathname is valid for a share.
 ********************************************************************/
 
-static char *valid_share_pathname(char *dos_pathname)
+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);
@@ -1419,25 +1494,11 @@ static char *valid_share_pathname(char *dos_pathname)
        if (strlen(dos_pathname) > 2 && ptr[1] == ':' && ptr[0] != '/')
                ptr += 2;
 
-       /* Only abolute paths allowed. */
+       /* Only absolute paths allowed. */
        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 +1515,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 = False;
 
        DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
 
@@ -1463,14 +1526,18 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
 
        r_u->parm_error = 0;
 
-       if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+       if ( strequal(share_name,"IPC$") 
+               || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+               || strequal(share_name,"global") )
+       {
                return WERR_ACCESS_DENIED;
+       }
 
        snum = find_service(share_name);
 
        /* Does this share exist ? */
        if (snum < 0)
-               return WERR_INVALID_NAME;
+               return WERR_NET_NAME_NOT_FOUND;
 
        /* No change to printer shares. */
        if (lp_print_ok(snum))
@@ -1478,7 +1545,11 @@ 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) {
@@ -1527,11 +1598,9 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
                        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:
                pstrcpy(pathname, lp_pathname(snum));
                fstrcpy(comment, lp_comment(snum));
@@ -1549,35 +1618,50 @@ 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()) {
+                       DEBUG(10,("_srv_net_share_set_info: No change share command\n"));
                        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 ));
-                       return WERR_ACCESS_DENIED;
+                               
+               /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
+       
+               if ( is_disk_op )
+                       become_root();
+                       
+               if ( (ret = smbrun(command, NULL)) == 0 ) {
+                       /* Tell everyone we updated smb.conf. */
+                       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
                }
+               
+               if ( is_disk_op )
+                       unbecome_root();
+                       
+               /********* END SeDiskOperatorPrivilege BLOCK *********/
 
-               /* Tell everyone we updated smb.conf. */
-               message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-
+               DEBUG(3,("_srv_net_share_set_info: Running [%s] returned (%d)\n", command, ret ));              
+       
+               if ( ret != 0 )
+                       return WERR_ACCESS_DENIED;
        } else {
                DEBUG(10,("_srv_net_share_set_info: No change to share name (%s)\n", share_name ));
        }
@@ -1595,7 +1679,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;
@@ -1615,8 +1699,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__));
 
@@ -1624,16 +1710,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. */
@@ -1666,7 +1752,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
        case 1006:
        case 1007:
                return WERR_ACCESS_DENIED;
-               break;
        case 1501:
                /* DFS only level. */
                return WERR_ACCESS_DENIED;
@@ -1675,8 +1760,12 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
                return WERR_UNKNOWN_LEVEL;
        }
 
-       if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+       if ( strequal(share_name,"IPC$") 
+               || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+               || strequal(share_name,"global") )
+       {
                return WERR_ACCESS_DENIED;
+       }
 
        snum = find_service(share_name);
 
@@ -1689,32 +1778,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 ( (ret = smbrun(command, NULL)) == 0 ) {
+               /* Tell everyone we updated smb.conf. */
+               message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, 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;
+
        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 ));
+               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 ));
+               }
        }
 
-       /* Tell everyone we updated smb.conf. */
-       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-
        /*
         * We don't call reload_services() here, the message will
         * cause this to be done before the next packet is read
@@ -1738,13 +1840,19 @@ 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__));
 
        unistr2_to_ascii(share_name, &q_u->uni_share_name, sizeof(share_name));
 
-       if (strequal(share_name,"IPC$") || strequal(share_name,"ADMIN$") || strequal(share_name,"global"))
+       if ( strequal(share_name,"IPC$") 
+               || ( lp_enable_asu_support() && strequal(share_name,"ADMIN$") )
+               || strequal(share_name,"global") )
+       {
                return WERR_ACCESS_DENIED;
+       }
 
        snum = find_service(share_name);
 
@@ -1757,27 +1865,44 @@ 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())
-               return WERR_ACCESS_DENIED;
+       is_disk_op = user_has_privileges( p->pipe_user.nt_user_token, &se_diskop );
 
-       if (!lp_delete_share_cmd() || !*lp_delete_share_cmd())
+       if (user.uid != sec_initial_uid()  && !is_disk_op ) 
                return WERR_ACCESS_DENIED;
 
+       if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) {
+               DEBUG(10,("_srv_net_share_del: No delete share command\n"));
+               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;
+
+       /********* BEGIN SeDiskOperatorPrivilege BLOCK *********/
+       
+       if ( is_disk_op )
+               become_root();
+
+       if ( (ret = smbrun(command, NULL)) == 0 ) {
+               /* Tell everyone we updated smb.conf. */
+               message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, 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;
+
        /* Delete the SD in the database. */
        delete_share_security(snum);
 
-       /* Tell everyone we updated smb.conf. */
-       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-
        lp_killservice(snum);
 
        return WERR_OK;
@@ -1800,7 +1925,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;
 
@@ -1849,8 +1974,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
        files_struct *fsp = NULL;
        SMB_STRUCT_STAT st;
        BOOL bad_path;
-       int access_mode;
-       int action;
        NTSTATUS nt_status;
        struct current_user user;
        connection_struct *conn = NULL;
@@ -1886,15 +2009,28 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
 
        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_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 (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_stat(conn, filename, &st);
        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), &action);
+                       fsp = open_directory(conn, filename, &st,
+                                       READ_CONTROL_ACCESS,
+                                       FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                       FILE_OPEN,
+                                       0,
+                                       NULL);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
@@ -1953,8 +2089,6 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
        files_struct *fsp = NULL;
        SMB_STRUCT_STAT st;
        BOOL bad_path;
-       int access_mode;
-       int action;
        NTSTATUS nt_status;
        struct current_user user;
        connection_struct *conn = NULL;
@@ -1990,16 +2124,30 @@ 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_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);
+
+       fsp = open_file_stat(conn, filename, &st);
 
        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), &action);
+                       fsp = open_directory(conn, filename, &st,
+                                               FILE_READ_ATTRIBUTES,
+                                               FILE_SHARE_READ|FILE_SHARE_WRITE,
+                                               FILE_OPEN,
+                                               0,
+                                               NULL);
 
                if (!fsp) {
                        DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
@@ -2027,11 +2175,13 @@ error_exit:
                close_file(fsp, True);
        }
 
-       if (became_user)
+       if (became_user) {
                unbecome_user();
+       }
 
-       if (conn) 
+       if (conn) {
                close_cnum(conn, user.vuid);
+       }
 
        return r_u->status;
 }
@@ -2095,16 +2245,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;