Changeset 3276 for pykota/trunk
- Timestamp:
- 01/08/08 00:03:01 (17 years ago)
- Location:
- pykota/trunk
- Files:
-
- 7 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/cupspykota
r3275 r3276 72 72 signal.signal(signal.SIGTERM, signal.SIG_IGN) 73 73 signal.signal(signal.SIGPIPE, signal.SIG_IGN) 74 self.oldSigIntHandler = signal.signal(signal.SIGINT, signal.SIG_IGN) 74 75 self.MyName = "PyKota" 75 76 self.myname = "cupspykota" … … 84 85 if not self.config.isAdmin : 85 86 from pykota import config 86 username = self. originalUserName87 username = self.effectiveUserName 87 88 raise config.PyKotaConfigError, _("User %(username)s is not allowed to read ~pykota/pykotadmin.conf, you must check the permissions.") % locals() 88 self.gotSigTerm = 089 self.disableSigInt()90 self.installSigTermHandler()91 92 def sigtermHandler(self, signum, frame) :93 """Sets an attribute whenever SIGTERM is received."""94 self.gotSigTerm = 195 self.printInfo(_("SIGTERM received, job %s cancelled.") % self.Ticket.JobId)96 os.environ["PYKOTASTATUS"] = "CANCELLED"97 98 def deinstallSigTermHandler(self) :99 """Deinstalls the SIGTERM handler."""100 self.logdebug("Deinstalling SIGTERM handler...")101 signal.signal(signal.SIGTERM, signal.SIG_IGN)102 self.logdebug("SIGTERM handler deinstalled.")103 104 def installSigTermHandler(self) :105 """Installs the SIGTERM handler."""106 self.logdebug("Installing SIGTERM handler...")107 signal.signal(signal.SIGTERM, self.sigtermHandler)108 self.logdebug("SIGTERM handler installed.")109 110 def disableSigInt(self) :111 """Disables the SIGINT signal (which raises KeyboardInterrupt)."""112 self.logdebug("Disabling SIGINT...")113 self.oldSigIntHandler = signal.signal(signal.SIGINT, signal.SIG_IGN)114 self.logdebug("SIGINT disabled.")115 89 116 90 def enableSigInt(self) : 117 91 """Enables the SIGINT signal (which raises KeyboardInterrupt).""" 118 self.logdebug("Enabling SIGINT...")119 92 signal.signal(signal.SIGINT, self.oldSigIntHandler) 120 self.logdebug("SIGINT enabled.")121 93 122 94 def waitForLock(self) : … … 153 125 Executes each existing backend in turn in device enumeration mode. 154 126 Returns the list of available backends. 127 128 Unfortunately this method can't output any debug information 129 to stdout or stderr, else CUPS considers that the device is 130 not available. 155 131 """ 156 # Unfortunately this method can't output any debug information157 # to stdout or stderr, else CUPS considers that the device is158 # not available.159 132 available = [] 160 133 (directory, myname) = os.path.split(sys.argv[0]) … … 226 199 return available 227 200 201 def checkCUPSVersion(self) : 202 """Checks if CUPS is not v1.3.4 or higher.""" 203 fullversion = os.environ.get("SOFTWARE", "") 204 if fullversion.startswith("CUPS/") : 205 vnum = fullversion.split("/")[1] 206 try : 207 (major, minor, release) = [int(p) for p in vnum.split(".")] 208 except ValueError : 209 pass 210 else : 211 return (major > 1) \ 212 or ((major == 1) and (minor > 3)) \ 213 or ((major == 1) and (minor == 3) and (release >= 4)) 214 return False 215 228 216 def initBackendParameters(self) : 229 217 """Initializes the backend's attributes.""" … … 233 221 # the environment before launching the real backend 234 222 self.logdebug("Initializing backend...") 223 224 if not self.checkCUPSVersion() : 225 self.printInfo("BEWARE : CUPS is too old. You must use CUPS v1.3.4 or higher.", "error") 235 226 236 227 self.PrinterName = os.environ.get("PRINTER", "") … … 410 401 self.logdebug("Launching subprocess [%s] to overwrite the job ticket." \ 411 402 % jobticketcommand) 412 self.regainPriv()413 403 inputfile = os.popen(jobticketcommand, "r") 414 404 try : … … 433 423 self.logdebug("IOError while reading subprocess' output : %s" % msg) 434 424 inputfile.close() 435 self.dropPriv()436 425 437 426 # now overwrite the job's ticket if new data was supplied … … 458 447 outfile = open(self.DataFile, "wb") 459 448 if self.Ticket.FileName is not None : 460 self.regainPriv()461 449 infile = open(self.Ticket.FileName, "rb") 462 450 self.logdebug("Reading input datas from %s" % self.Ticket.FileName) … … 481 469 if mustclose : 482 470 infile.close() 483 self.dropPriv()484 471 485 472 outfile.close() … … 494 481 """Cleans up the place.""" 495 482 self.logdebug("Cleaning up...") 496 self.regainPriv()497 self.deinstallSigTermHandler()498 483 if (self.DataFile is not None) and os.path.exists(self.DataFile) : 499 484 try : … … 933 918 if mailto == "EXTERNAL" : 934 919 # TODO : clean this again 935 self.regainPriv()936 920 self.externalMailTo(arguments, self.Action, self.User, self.Printer, self.Reason) 937 self.dropPriv()938 921 else : 939 922 # TODO : clean this again … … 1114 1097 else : 1115 1098 self.printInfo(_("Job accounting begins.")) 1116 self.deinstallSigTermHandler()1117 1099 self.accounter.beginJob(self.Printer) 1118 self.installSigTermHandler()1119 1100 1120 1101 # handle starting banner pages with accounting 1121 1102 if (self.Action != "CANCEL") and accountbanner in ["STARTING", "BOTH"] : 1122 if not self.gotSigTerm : 1123 self.handleBanner("starting", 1) 1124 1125 # pass the job's data to the real backend 1126 if (not self.gotSigTerm) and (self.Action in ["ALLOW", "WARN"]) : 1103 self.handleBanner("starting", 1) 1104 1105 # pass the job's data to the real backend if needed 1106 if self.Action in ("ALLOW", "WARN") : 1127 1107 retcode = self.printJobDatas() 1128 1108 else : … … 1134 1114 # handle ending banner pages with accounting 1135 1115 if (self.Action != "CANCEL") and accountbanner in ["ENDING", "BOTH"] : 1136 if not self.gotSigTerm : 1137 self.handleBanner("ending", 1) 1116 self.handleBanner("ending", 1) 1138 1117 1139 1118 # stops accounting … … 1143 1122 self.printInfo(_("Job cancelled, no accounting has been done.")) 1144 1123 else : 1145 self.deinstallSigTermHandler()1146 1124 self.accounter.endJob(self.Printer) 1147 self.installSigTermHandler()1148 1125 self.printInfo(_("Job accounting ends.")) 1149 1126 … … 1284 1261 1285 1262 self.logdebug("Starting original backend %s with args %s" % (originalbackend, " ".join(['"%s"' % a for a in arguments]))) 1286 self.regainPriv()1287 1263 pid = os.fork() 1288 1264 self.logdebug("Forked !") … … 1298 1274 self.logdebug("We shouldn't be there !!!") 1299 1275 os._exit(-1) 1300 self.dropPriv()1301 1276 1302 1277 self.logdebug("Waiting for original backend to exit...") 1303 killed = 01278 killed = False 1304 1279 status = -1 1305 1280 while status == -1 : … … 1307 1282 status = os.waitpid(pid, 0)[1] 1308 1283 except OSError, (err, msg) : 1309 if (err == 4) and self.gotSigTerm : 1310 os.kill(pid, signal.SIGTERM) 1311 killed = 1 1284 if err == 4 : 1285 killed = True 1312 1286 1313 1287 if os.WIFEXITED(status) : … … 1325 1299 self.Reason = "CUPS backend %s died abnormally." % originalbackend 1326 1300 self.printInfo(self.Reason, "error") 1327 return -11301 return 1 1328 1302 else : 1329 1303 self.Reason = "CUPS backend %s was killed." % originalbackend -
pykota/trunk/bin/pkinvoice
r3275 r3276 198 198 pageCompression=1) 199 199 200 c.setAuthor(self. originalUserName)200 c.setAuthor(self.effectiveUserName) 201 201 c.setTitle("PyKota invoices") 202 202 c.setSubject("Invoices generated with PyKota") -
pykota/trunk/bin/pknotify
r3275 r3276 180 180 retcode = False 181 181 self.password = password 182 self.regainPriv()183 182 auth = PAM.pam() 184 183 auth.start("passwd") … … 195 194 self.logdebug(_("Password correct for user %s") % username) 196 195 retcode = True 197 self.dropPriv()198 196 return retcode 199 197 -
pykota/trunk/bin/pkprinters
r3275 r3276 171 171 if uri and (not self.isPrinterCaptured(deviceuri=uri)) : 172 172 newuri = "cupspykota://%s" % uri 173 self.regainPriv() # to avoid having to enter password.174 173 os.system('lpadmin -p "%s" -v "%s"' % (printer.Name, newuri)) 175 174 self.logdebug("Printer %s rerouted to %s" % (printer.Name, newuri)) 176 self.dropPriv()177 175 178 176 def deroutePrinterFromPyKota(self, printer) : … … 183 181 if newuri.startswith("//") : 184 182 newuri = newuri[2:] 185 self.regainPriv() # to avoid having to enter password.186 183 os.system('lpadmin -p "%s" -v "%s"' % (printer.Name, newuri)) 187 184 self.logdebug("Printer %s rerouted to %s" % (printer.Name, newuri)) 188 self.dropPriv()189 185 190 186 def main(self, names, options) : -
pykota/trunk/bin/pkrefund
r3275 r3276 209 209 pageCompression=1) 210 210 211 c.setAuthor(self. originalUserName)211 c.setAuthor(self.effectiveUserName) 212 212 c.setTitle("PyKota print job refunding receipts") 213 213 c.setSubject("Print job refunding receipts generated with PyKota") -
pykota/trunk/pykota/storage.py
r3275 r3276 489 489 % (self.JobSize, 490 490 self.JobPrice, 491 self.parent.tool. originalUserName,491 self.parent.tool.effectiveUserName, 492 492 os.getlogin(), 493 493 str(DateTime.now())[:19]) -
pykota/trunk/pykota/tool.py
r3275 r3276 132 132 self.logger = logger.openLogger("stderr") 133 133 134 # did we drop priviledges ?135 self.privdropped = 0136 137 134 # locale stuff 138 135 try : … … 167 164 # pykota specific stuff 168 165 self.documentation = doc 166 167 # Extract the effective username 168 uid = os.geteuid() 169 try : 170 self.effectiveUserName = pwd.getpwuid(uid)[0] 171 except (KeyError, IndexError), msg : 172 self.printInfo(_("Strange problem with uid(%s) : %s") % (uid, msg), "warn") 173 self.effectiveUserName = os.getlogin() 169 174 170 175 def deferredInit(self) : … … 190 195 self.logger = logger.openLogger(self.config.getLoggingBackend()) 191 196 192 # now drop priviledge if possible193 self.dropPriv()194 195 197 # We NEED this here, even when not in an accounting filter/backend 196 198 self.softwareJobSize = 0 … … 208 210 arguments = " ".join(['"%s"' % arg for arg in sys.argv]) 209 211 self.logdebug("Command line arguments : %s" % arguments) 210 211 def dropPriv(self) :212 """Drops priviledges."""213 uid = os.geteuid()214 try :215 self.originalUserName = pwd.getpwuid(uid)[0]216 except (KeyError, IndexError), msg :217 self.printInfo(_("Strange problem with uid(%s) : %s") % (uid, msg), "warn")218 self.originalUserName = None219 else :220 if uid :221 self.logdebug(_("Running as user '%s'.") % self.originalUserName)222 else :223 if self.pykotauser is None :224 self.logdebug(_("No user named 'pykota'. Not dropping priviledges."))225 else :226 try :227 os.setegid(self.pykotauser[3])228 os.seteuid(self.pykotauser[2])229 except OSError, msg :230 self.printInfo(_("Impossible to drop priviledges : %s") % msg, "warn")231 else :232 self.logdebug(_("Priviledges dropped. Now running as user 'pykota'."))233 self.privdropped = 1234 235 def regainPriv(self) :236 """Drops priviledges."""237 if self.privdropped :238 try :239 os.seteuid(0)240 os.setegid(0)241 except OSError, msg :242 self.printInfo(_("Impossible to regain priviledges : %s") % msg, "warn")243 else :244 self.logdebug(_("Regained priviledges. Now running as root."))245 self.privdropped = 0246 212 247 213 def UTF8ToUserCharset(self, text) :