root / pykota / trunk / bin / pkmail @ 1953

Revision 1953, 6.7 kB (checked in by jalet, 19 years ago)

Added some kind of protection against bad guys

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# An email gateway for PyKota
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.2  2004/11/21 22:16:11  jalet
27# Added some kind of protection against bad guys
28#
29# Revision 1.1  2004/11/21 21:50:03  jalet
30# Introduced the new pkmail command as a simple email gateway
31#
32
33import sys
34import os
35import popen2
36import smtplib
37import email
38
39from pykota.tool import PyKotaTool, PyKotaToolError, crashed, N_
40from pykota.pdlanalyzer import PDLAnalyzer, PDLAnalyzerError
41
42__doc__ = N_("""pkmail v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
43
44Email gateway for PyKota.
45
46command line usage :
47
48  pkmail  [options]
49
50options :
51
52  -v | --version       Prints pkmail's version number then exits.
53  -h | --help          Prints this message then exits.
54 
55   
56  This command is meant to be used from your mail server's aliases file,
57  as a pipe. It will then accept commands send to it in email messages,
58  and will send the answer to the command's originator.
59 
60  To use this command, create an email alias in /etc/aliases with
61  the following format :
62 
63    pykotacmd: "|/usr/bin/pkmail"
64   
65  Then run the 'newaliases' command to regenerate the aliases database.
66 
67  You can now send commands by email to 'pykotacmd@yourdomain.com', with
68  the command in the subject.
69 
70  List of supported commands :
71 
72        report [username]
73 
74  NB : For pkmail to work correctly, you may have to put the 'mail'
75  system user in the 'lpadmin' system group to ensure this user can
76  read the /etc/pykota/pykotadmin.conf file, and restart your
77  mail server (e.g. /etc/init.d/exim restart). It is strongly advised
78  that you think at least twice before doing this though.
79 
80  Use at your own risk !
81 
82This program is free software; you can redistribute it and/or modify
83it under the terms of the GNU General Public License as published by
84the Free Software Foundation; either version 2 of the License, or
85(at your option) any later version.
86
87This program is distributed in the hope that it will be useful,
88but WITHOUT ANY WARRANTY; without even the implied warranty of
89MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
90GNU General Public License for more details.
91
92You should have received a copy of the GNU General Public License
93along with this program; if not, write to the Free Software
94Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
95
96Please e-mail bugs to: %s""")
97       
98       
99class PKMail(PyKotaTool) :       
100    """A class for pkmail."""
101    def main(self, files, options) :
102        """Accepts commands passed in an email message."""
103        data = sys.stdin.read()
104        message = email.message_from_string(data)
105        useremail = message["From"]
106        whoami = message["To"]
107        cmdargs = message["Subject"].split()
108        try :
109            (command, arguments) = (cmdargs[0].capitalize(), cmdargs[1:])
110        except IndexError :   
111            raise PyKotaToolError, "No command found !"
112       
113        badchars = """/<>&"'#!%*$,;\\"""
114        cheatmeonce = 0
115        for c in "".join(arguments) :
116            if c in badchars :
117                cheatmeonce = 1
118           
119        if cheatmeonce :   
120            self.logdebug("Possible intruder at %s : %s" % (useremail, str(arguments)))
121            result = "Either you mistyped your command, or you're a bad guy !"
122        else :
123            self.logdebug("Launching internal command '%s' with arguments %s" % (command, str(arguments)))
124            cmdfunc = getattr(self, "cmd%s" % command, self.cmdDefault)
125            result = cmdfunc(arguments)
126       
127        self.logdebug("Sending answer to : %s" % useremail)
128        server = smtplib.SMTP(self.smtpserver)
129        server.sendmail(whoami, [ useremail ], "From: %s\nTo: %s\nSubject: Result of your commands\n\n%s\n" % (whoami, useremail, result))
130        server.quit()
131        self.logdebug("Answer sent to : %s" % useremail)
132       
133        return 0
134       
135    def runCommand(self, cmd) :   
136        """Executes a command."""
137        self.logdebug("Launching : '%s'" % cmd)
138        os.environ["PATH"] = "%s:/bin:/usr/bin:/usr/local/bin:/opt/bin:/sbin:/usr/sbin" % os.environ.get("PATH", "")
139        child = popen2.Popen3(cmd)
140        child.tochild.close()
141        result = child.fromchild.read()
142        status = child.wait()
143        if os.WIFEXITED(status) :
144            status = os.WEXITSTATUS(status)
145        self.logdebug("'%s' exited with status %s" % (cmd, status))
146        return result
147       
148    def cmdDefault(self, arguments) :   
149        """Default command : sends an 'unknown command' message."""
150        return "Unknown command."
151       
152    def cmdReport(self, args) :   
153        """Generates a print quota report."""
154        return self.runCommand("repykota %s" % ' '.join([ '"%s"' % a for a in args ]))
155           
156if __name__ == "__main__" : 
157    retcode = 0
158    try :
159        defaults = { \
160                   }
161        short_options = "vh"
162        long_options = ["help", "version"]
163       
164        # Initializes the command line tool
165        mailparser = PKMail(doc=__doc__)
166       
167        # parse and checks the command line
168        (options, args) = mailparser.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
169       
170        # sets long options
171        options["help"] = options["h"] or options["help"]
172        options["version"] = options["v"] or options["version"]
173       
174        if options["help"] :
175            mailparser.display_usage_and_quit()
176        elif options["version"] :
177            mailparser.display_version_and_quit()
178        else :
179            retcode = mailparser.main(args, options)
180    except SystemExit :       
181        pass
182    except :
183        try :
184            mailparser.crashed("pkmail failed")
185        except :   
186            crashed("pkmail failed")
187        retcode = -1
188
189    try :
190        mailparser.storage.close()
191    except (TypeError, NameError, AttributeError) :   
192        pass
193       
194    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.