r4825: Printing changes
authorGerald Carter <jerry@samba.org>
Tue, 18 Jan 2005 19:51:36 +0000 (19:51 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:53:56 +0000 (10:53 -0500)
----------------

* bracket the add/delete/set printer scripts with checks for se_print_op
* slight change to the add/set printer script semantics.  smbd no longer
  relies on output from the script (on stdout) to re-read smb.conf
* remove SIGHUP from set/add/delete printin script code and now just
  use MSG_SMB_CONF_UPDATED

* bracket the add/delete/set share scripts with checks for se_print_op
  (this includes setting share ACLs)

source/rpc_server/srv_spoolss_nt.c
source/rpc_server/srv_srvsvc_nt.c

index 12611c4ee5a399259fc8b80fce03a7162d52528f..31e1e4a3bf5a5ba7ede626c2584795084a1b5119 100644 (file)
@@ -379,29 +379,50 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
                return WERR_ACCESS_DENIED;
        }
 #endif
-
+       
+       /* this does not need a become root since the access check has been 
+          done on the handle already */
+          
        if (del_a_printer( Printer->sharename ) != 0) {
                DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
                return WERR_BADFID;
        }
 
+       /* the delete printer script shoudl be run as root if the user has perms */
+       
        if (*lp_deleteprinter_cmd()) {
 
                char *cmd = lp_deleteprinter_cmd();
                pstring command;
                int ret;
-
+               SE_PRIV se_printop = SE_PRINT_OPERATOR;
+               BOOL is_print_op;
+               
                pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
 
+               is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
+       
                DEBUG(10,("Running [%s]\n", command));
+
+               /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
+       
+               if ( is_print_op )
+                       become_root();
+               
                ret = smbrun(command, NULL);
-               if (ret != 0) {
-                       return WERR_BADFID; /* What to return here? */
-               }
+               
+               if ( is_print_op )
+                       unbecome_root();
+
+               /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
+
                DEBUGADD(10,("returned [%d]\n", ret));
 
-               /* Send SIGHUP to process group... is there a better way? */
-               kill(0, SIGHUP);
+               if (ret != 0) 
+                       return WERR_BADFID; /* What to return here? */
+
+               /* Tell everyone we updated smb.conf. */
+               message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
 
                /* go ahead and re-read the services immediately */
                reload_services( False );
@@ -5984,7 +6005,7 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
 /****************************************************************************
 ****************************************************************************/
 
-static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
+static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
 {
        extern userdom_struct current_user_info;
        char *cmd = lp_addprinter_cmd();
@@ -5994,6 +6015,8 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
        int ret;
        int fd;
        fstring remote_machine = "%m";
+       SE_PRIV se_printop = SE_PRINT_OPERATOR;
+       BOOL is_print_op;
 
        standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
        
@@ -6002,8 +6025,22 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
                        printer->info_2->portname, printer->info_2->drivername,
                        printer->info_2->location, printer->info_2->comment, remote_machine);
 
+       is_print_op = user_has_privileges( token, &se_printop );
+
        DEBUG(10,("Running [%s]\n", command));
+
+       /********* BEGIN SePrintOperatorPrivilege **********/
+
+       if ( is_print_op )
+               become_root();
+       
        ret = smbrun(command, &fd);
+
+       if ( is_print_op )
+               unbecome_root();
+
+       /********* END SePrintOperatorPrivilege **********/
+
        DEBUGADD(10,("returned [%d]\n", ret));
 
        if ( ret != 0 ) {
@@ -6012,22 +6049,25 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
                return False;
        }
 
+       /* Tell everyone we updated smb.conf. */
+       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+
+       /* reload our services immediately */
+       reload_services( False );
+
        numlines = 0;
        /* Get lines and convert them back to dos-codepage */
        qlines = fd_lines_load(fd, &numlines);
        DEBUGADD(10,("Lines returned = [%d]\n", numlines));
        close(fd);
 
-       if(numlines) {
+       /* Set the portname to what the script says the portname should be. */
+       /* but don't require anything to be return from the script exit a good error code */
+
+       if (numlines) {
                /* Set the portname to what the script says the portname should be. */
                strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
                DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
-
-               /* Send SIGHUP to process group... is there a better way? */
-               kill(0, SIGHUP);
-               
-               /* reload our services immediately */
-               reload_services( False );
        }
 
        file_lines_free(qlines);
@@ -6122,7 +6162,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
                        || !strequal(printer->info_2->portname, old_printer->info_2->portname)
                        || !strequal(printer->info_2->location, old_printer->info_2->location)) )
        {
-               if ( !add_printer_hook(printer) ) {
+               if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
                        result = WERR_ACCESS_DENIED;
                        goto done;
                }
@@ -7416,7 +7456,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
           trying to add a printer like this  --jerry */
 
        if (*lp_addprinter_cmd() ) {
-               if ( !add_printer_hook(printer) ) {
+               if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
                        free_a_printer(&printer,2);
                        return WERR_ACCESS_DENIED;
        }
index af4c94800a5e3d711ade294ac3aab42fdd895814..382941d3613e600679b92911de36cb994ec595ea 100644 (file)
@@ -1470,6 +1470,8 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
        int ret;
        char *ptr;
        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__));
 
@@ -1492,7 +1494,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) {
@@ -1575,23 +1581,36 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
                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(ptr, 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);
 
                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 ));
        }
@@ -1609,7 +1628,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;
@@ -1631,6 +1650,8 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
        int ret;
        char *ptr;
        SEC_DESC *psd = NULL;
+       SE_PRIV se_diskop = SE_DISK_OPERATOR;
+       BOOL is_disk_op;
 
        DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
 
@@ -1638,16 +1659,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. */
@@ -1713,12 +1734,28 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
 
        slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
                        lp_add_share_cmd(), dyn_CONFIGFILE, share_name, ptr, 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 ));
+       
+       /********* 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_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))
@@ -1726,9 +1763,6 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
                                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
@@ -1752,6 +1786,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__));
 
@@ -1771,27 +1807,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;