~ubuntu-branches/ubuntu/utopic/nss-pam-ldapd/utopic-proposed

« back to all changes in this revision

Viewing changes to pynslcd/pynslcd.py

  • Committer: Package Import Robot
  • Author(s): Arthur de Jong
  • Date: 2011-12-31 13:30:00 UTC
  • Revision ID: package-import@ubuntu.com-20111231133000-c2lpa27xp5s6q481
Tags: 0.8.5
* support larger gecos values (closes: #640781)
* updated Swedish debconf translation by Martin Bagge (closes: #640623)
* consistently handle whitespace in configuration file during package
  configuration (thanks Nick) (closes: #641619)
* add a versioned dependency on libpam0g to ensure the PAM libraries are
  multiarch-aware
* in debconf, treat the "hard" value for tls_reqcert as if it was "demand"
  (closes: #642347)
* reduce loglevel of user not found messages to avoid spamming the logs
  with useless information (thanks Wakko Warner) (closes: #641820)
* other logging improvements
* keep nslcd running during package upgrades (closes: #644892)
* explicitly parse numbers as base 10 (thanks Jakub Hrozek)
* implement FreeBSD group membership NSS function (thanks Tom Judge)
* fix an issue where changes in /etc/nsswitch.conf were not correctly
  picked up and could lead to lookups being disabled on upgrade
  (closes: #645599)
* fix an issue with detecting the uid of the calling process and log
  denied shadow requests in debug mode
* fix a typo in the disconnect logic code (thanks Martin Poole)
* enable hardening options during build
* implement configuration file handling in pynslcd and other pynslcd
  improvements (pynslcd is not in a Debian package yet)
* update debian/copyright

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
from tio import TIOStream
38
38
 
39
39
 
 
40
# the name of the program
 
41
program_name = 'pynslcd'
 
42
 
 
43
# flag to indicate whether we are in debugging mode
 
44
debugging = 0
 
45
 
 
46
# flag to indicate user requested the --check option
 
47
checkonly = False
 
48
 
 
49
 
40
50
# configure logging
41
51
class MyFormatter(logging.Formatter):
42
52
    def format(self, record):
61
71
#syslog.setFormatter(formatter)
62
72
#logger.addHandler(syslog)
63
73
 
 
74
 
64
75
def display_version(fp):
65
76
    fp.write('%(PACKAGE_STRING)s\n'
66
77
             'Written by Arthur de Jong.\n'
68
79
             'Copyright (C) 2010, 2011 Arthur de Jong\n'
69
80
             'This is free software; see the source for copying conditions.  There is NO\n'
70
81
             'warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n'
71
 
             % { 'PACKAGE_STRING': config.PACKAGE_STRING, } )
 
82
             % {'PACKAGE_STRING': config.PACKAGE_STRING, })
 
83
 
72
84
 
73
85
def display_usage(fp):
74
86
    fp.write("Usage: %(program_name)s [OPTION]...\n"
79
91
             "      --version      output version information and exit\n"
80
92
             "\n"
81
93
             "Report bugs to <%(PACKAGE_BUGREPORT)s>.\n"
82
 
             % { 'program_name': cfg.program_name,
83
 
                 'PACKAGE_BUGREPORT': config.PACKAGE_BUGREPORT, } )
 
94
             % {'program_name': program_name,
 
95
                'PACKAGE_BUGREPORT': config.PACKAGE_BUGREPORT, })
 
96
 
84
97
 
85
98
def parse_cmdline():
86
99
    """Parse command-line arguments."""
87
100
    import getopt
88
 
    cfg.program_name = sys.argv[0] or 'pynslcd'
 
101
    global program_name
 
102
    program_name = sys.argv[0] or program_name
89
103
    try:
90
104
        optlist, args = getopt.gnu_getopt(sys.argv[1:],
91
105
          'cdhV', ('check', 'debug', 'help', 'version', ))
92
106
        for flag, arg in optlist:
93
107
            if flag in ('-c', '--check'):
94
 
                cfg.check = True
 
108
                global checkonly
 
109
                checkonly = True
95
110
            elif flag in ('-d', '--debug'):
96
 
                cfg.debug += 1
 
111
                global debugging
 
112
                debugging += 1
97
113
            elif flag in ('-h', '--help'):
98
114
                display_usage(sys.stdout)
99
115
                sys.exit(0)
105
121
    except getopt.GetoptError, reason:
106
122
        sys.stderr.write("%(program_name)s: %(reason)s\n"
107
123
                         "Try '%(program_name)s --help' for more information.\n"
108
 
                          % { 'program_name': cfg.program_name,
109
 
                              'reason': reason, })
 
124
                          % {'program_name': program_name,
 
125
                             'reason': reason, })
110
126
        sys.exit(1)
111
127
 
 
128
 
112
129
def create_socket():
113
130
    """Returns a socket ready to answer requests from the client."""
114
131
    import socket
118
135
    try:
119
136
        os.unlink(config.NSLCD_SOCKET)
120
137
    except OSError:
121
 
        pass # ignore any problems
 
138
        pass  # ignore any problems
122
139
    # bind to named socket
123
140
    sock.bind((config.NSLCD_SOCKET))
124
141
    # close the file descriptor on exit
129
146
    sock.listen(socket.SOMAXCONN)
130
147
    return sock
131
148
 
 
149
 
132
150
def log_newsession():
133
151
    pass
134
152
    # FIXME: implement
135
153
 
 
154
 
136
155
def getpeercred(fd):
137
156
    return (None, None, None)
138
157
    # FIXME: implement and return uid, gid, pid
139
158
 
 
159
 
140
160
handlers = {}
141
161
handlers.update(common.get_handlers('alias'))
142
162
handlers.update(common.get_handlers('ether'))
151
171
handlers.update(common.get_handlers('service'))
152
172
handlers.update(common.get_handlers('shadow'))
153
173
 
 
174
 
154
175
def acceptconnection(session):
155
176
    # accept a new connection
156
177
    conn, addr = nslcd_serversocket.accept()
165
186
            uid, gid, pid = getpeercred(conn)
166
187
            logging.debug('connection from pid=%r uid=%r gid=%r', pid, uid, gid)
167
188
        except:
168
 
            raise # FIXME: handle exception gracefully
 
189
            raise  # FIXME: handle exception gracefully
169
190
        # create a stream object
170
191
        fp = TIOStream(conn)
171
192
        # read request
184
205
        if fp:
185
206
            fp.close()
186
207
 
 
208
 
187
209
def disable_nss_ldap():
188
210
    """Disable the nss_ldap module to avoid lookup loops."""
189
211
    import ctypes
190
212
    lib = ctypes.CDLL(config.NSS_LDAP_SONAME)
191
213
    ctypes.c_int.in_dll(lib, '_nss_ldap_enablelookups').value = 0
192
214
 
 
215
 
193
216
def worker():
194
217
    # create a new LDAP session
195
218
    #session = myldap_create_session()
196
 
    session = ldap.initialize(cfg.ldap_uri)
 
219
    session = ldap.initialize(cfg.uri)
197
220
    # start waiting for incoming connections
198
221
    while True:
199
222
        # wait for a new connection
200
223
        acceptconnection(session)
201
224
        # FIXME: handle exceptions
202
225
 
 
226
 
203
227
if __name__ == '__main__':
204
228
    # parse options
205
229
    parse_cmdline()
211
235
    # disable ldap lookups of host names to avoid lookup loop
212
236
    disable_nss_ldap()
213
237
    # set log level
214
 
    if cfg.debug:
 
238
    if debugging:
215
239
        logging.getLogger().setLevel(logging.DEBUG)
216
240
    # FIXME: implement
217
241
    #if myldap_set_debuglevel(cfg.debug) != LDAP_SUCCESS:
218
242
    #    sys.exit(1)
219
243
    # read configuration file
220
244
    cfg.read(config.NSLCD_CONF_PATH)
 
245
    # FIXME: set tls_cacertdir, tls_cacertfile, tls_randfile, tls_ciphers, tls_cert, tls_key options immediately after parsing config
221
246
    # set a default umask for the pidfile and socket
222
247
    os.umask(0022)
223
248
    # see if someone already locked the pidfile
224
249
    pidfile = mypidfile.MyPIDLockFile(config.NSLCD_PIDFILE)
225
250
    # see if --check option was given
226
 
    if cfg.check:
 
251
    if checkonly:
227
252
        if pidfile.is_locked():
228
253
            logging.debug('pidfile (%s) is locked', config.NSLCD_PIDFILE)
229
254
            sys.exit(0)
235
260
        logging.error('daemon may already be active, cannot acquire lock (%s)', config.NSLCD_PIDFILE)
236
261
        sys.exit(1)
237
262
    # daemonize
238
 
    if cfg.debug:
 
263
    if debugging:
239
264
        daemon = pidfile
240
265
    else:
241
266
        daemon = daemon.DaemonContext(
242
267
                      pidfile=pidfile,
243
268
                      signal_map={
244
269
                          signal.SIGTERM: 'terminate',
245
 
                          signal.SIGINT:  'terminate',
 
270
                          signal.SIGINT: 'terminate',
246
271
                          signal.SIGPIPE: None,
247
272
                      })
248
273
    # start daemon
249
274
    with daemon:
250
275
        # start normal logging
251
 
        if not cfg.debug:
 
276
        if not debugging:
252
277
            log_startlogging()
253
278
        logging.info('version %s starting', config.VERSION)
254
279
        # create socket