From 10861a6160fb1ead19e23ff58f3590813600fc7b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 18 Jan 2005 19:51:36 +0000 Subject: r4825: Printing changes ---------------- * 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) (This used to be commit 8ab8113d2e1bec6a1dbf464882ad724c7c591be4) --- source3/rpc_server/srv_spoolss_nt.c | 74 +++++++++++++++++++------ source3/rpc_server/srv_srvsvc_nt.c | 107 ++++++++++++++++++++++++++---------- 2 files changed, 136 insertions(+), 45 deletions(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 12611c4ee5..31e1e4a3bf 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -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; } diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index af4c94800a..382941d361 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -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; -- cgit