|
1 |
#!/usr/bin/python2.6 |
1 |
#!/usr/bin/python2.6 |
2 |
# -*- coding: utf-8 -*- |
2 |
# -*- coding: utf-8 -*- |
3 |
# |
3 |
# |
4 |
# Univention Admin Modules |
4 |
"""Univention Directory Manager command line server""" |
5 |
# the comannd line server |
|
|
6 |
# |
5 |
# |
7 |
# Copyright 2004-2012 Univention GmbH |
6 |
# Copyright 2004-2013 Univention GmbH |
8 |
# |
7 |
# |
9 |
# http://www.univention.de/ |
8 |
# http://www.univention.de/ |
10 |
# |
9 |
# |
|
31 |
# /usr/share/common-licenses/AGPL-3; if not, see |
30 |
# /usr/share/common-licenses/AGPL-3; if not, see |
32 |
# <http://www.gnu.org/licenses/>. |
31 |
# <http://www.gnu.org/licenses/>. |
33 |
|
32 |
|
34 |
|
|
|
35 |
import SocketServer |
33 |
import SocketServer |
36 |
import socket |
34 |
import socket |
37 |
import select |
35 |
from select import select |
38 |
import os |
36 |
import os |
39 |
import sys |
37 |
import sys |
40 |
import traceback |
38 |
import traceback |
41 |
import univention.config_registry |
39 |
from univention.config_registry import ConfigRegistry |
42 |
import univention.debug |
40 |
import univention.debug as ud |
43 |
import univention.admincli.adduser |
41 |
import univention.admincli.adduser |
44 |
import univention.admincli.admin |
42 |
import univention.admincli.admin |
45 |
import univention.admincli.passwd |
43 |
import univention.admincli.passwd |
|
|
44 |
import signal |
46 |
try: |
45 |
try: |
47 |
import univention.admincli.license_check |
46 |
import univention.admincli.license_check |
48 |
licenseImportError=False |
47 |
licenseImportError = False |
49 |
except ImportError: |
48 |
except ImportError: |
50 |
licenseImportError=True |
49 |
licenseImportError = True |
51 |
|
50 |
|
52 |
logfile='' |
51 |
logfile = '' |
53 |
|
52 |
|
54 |
class myRequestHandler(SocketServer.BaseRequestHandler): |
53 |
class MyRequestHandler(SocketServer.BaseRequestHandler): |
|
|
54 |
"""Handle request on listeneing socket to open new connection.""" |
55 |
def handle(self): |
55 |
def handle(self): |
56 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] new connection [%s]' % (os.getppid(), os.getpid())) |
56 |
ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] new connection [%s]' % (os.getppid(), os.getpid())) |
57 |
sarglist='' |
57 |
sarglist = '' |
58 |
while 1: |
58 |
while True: |
59 |
buf = self.request.recv(1024) |
59 |
buf = self.request.recv(1024) |
60 |
if buf[-1] == '\0': |
60 |
if buf[-1] == '\0': |
61 |
buf = buf[0:-1] |
61 |
buf = buf[:-1] |
62 |
sarglist += buf |
62 |
sarglist += buf |
63 |
break |
63 |
break |
64 |
else: |
64 |
else: |
65 |
sarglist += buf |
65 |
sarglist += buf |
66 |
doit(sarglist, self.request) |
66 |
doit(sarglist, self.request) |
67 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] connection closed [%s]' % (os.getppid(), os.getpid())) |
67 |
ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] connection closed [%s]' % (os.getppid(), os.getpid())) |
68 |
|
|
|
69 |
|
68 |
|
70 |
def finish(self): |
69 |
def finish(self): |
71 |
pass |
70 |
pass |
72 |
|
71 |
|
73 |
class ForkingTCPServer(SocketServer.ForkingTCPServer): |
|
|
74 |
|
72 |
|
75 |
address_family=socket.AF_UNIX |
73 |
class ForkingTCPServer(SocketServer.ForkingTCPServer): |
|
|
74 |
"""UDM server listening on UNIX socket.""" |
75 |
address_family = socket.AF_UNIX |
76 |
allow_reuse_address = 1 |
76 |
allow_reuse_address = 1 |
77 |
def server_bind(self): |
77 |
def server_bind(self): |
78 |
SocketServer.TCPServer.server_bind(self) |
78 |
SocketServer.TCPServer.server_bind(self) |
79 |
host, port = self.socket.getsockname()[:2] |
79 |
_host, port = self.socket.getsockname()[:2] |
80 |
self.server_name = 'localhost' #socket.getfqdn(host) |
80 |
self.server_name = 'localhost' #socket.getfqdn(host) |
81 |
self.server_port = port |
81 |
self.server_port = port |
82 |
|
82 |
|
|
|
83 |
|
83 |
def main(): |
84 |
def main(): |
|
|
85 |
"""UDM command line server.""" |
84 |
global logfile |
86 |
global logfile |
85 |
logfile='' |
87 |
try: |
86 |
if len(sys.argv) < 2: |
88 |
logfile = sys.argv[1] |
87 |
logfile='/var/log/univention/directory-manager-cmd.log' |
89 |
except IndexError: |
88 |
else: |
90 |
logfile = '/var/log/univention/directory-manager-cmd.log' |
89 |
logfile=sys.argv[1] |
|
|
90 |
|
91 |
|
91 |
socket_dir='/tmp/admincli_%s/' % os.getuid() |
92 |
socket_dir = '/tmp/admincli_%s/' % os.getuid() |
92 |
socket_filename='sock' |
93 |
socket_filename = 'sock' |
93 |
socket_path=(socket_dir+socket_filename) |
94 |
socket_path = (socket_dir+socket_filename) |
94 |
|
95 |
|
95 |
univention.debug.init(logfile, 1, 0) |
96 |
ud.init(logfile, ud.FLUSH, ud.NO_FUNCTION) |
96 |
|
97 |
|
97 |
if os.path.isfile('%s.run' % socket_path): |
98 |
runfilename = '%s.run' % socket_path |
98 |
runs=1 |
99 |
if os.path.isfile(runfilename): |
99 |
runfile=open('%s.run' % socket_path, 'r') |
|
|
100 |
line=runfile.readlines() |
101 |
runfile.close() |
102 |
try: |
100 |
try: |
103 |
pid=line[0] |
101 |
with open(runfilename, 'r') as runfile: |
104 |
except: |
102 |
line = runfile.readline().strip() |
105 |
pid='' |
103 |
pid = int(line) |
106 |
if len(pid)>0 and pid[-1:] == '\n': |
104 |
os.kill(pid, signal.SIGCONT) |
107 |
pid = pid[:-1] |
105 |
except (ValueError, OSError): |
108 |
if pid: |
106 |
pid = 0 |
109 |
try: |
|
|
110 |
os.kill(int(pid), 18) |
111 |
except OSError: |
112 |
pid='' |
113 |
if not pid: # no pid found or no server running |
107 |
if not pid: # no pid found or no server running |
114 |
runs=0 |
|
|
115 |
os.unlink(socket_path) |
108 |
os.unlink(socket_path) |
116 |
os.unlink('%s.run' % socket_path) |
109 |
os.unlink(runfilename) |
117 |
os.rmdir(socket_dir) |
110 |
os.rmdir(socket_dir) |
118 |
if not runs==0: |
111 |
else: |
119 |
print 'E: Server already running [Pid: %s]' % pid |
112 |
print >> sys.stderr, 'E: Server already running [Pid: %s]' % pid |
120 |
sys.exit(1) |
113 |
sys.exit(1) |
121 |
|
114 |
|
122 |
configRegistry=univention.config_registry.ConfigRegistry() |
115 |
configRegistry = ConfigRegistry() |
123 |
configRegistry.load() |
116 |
configRegistry.load() |
124 |
if configRegistry.has_key('directory/manager/cmd/debug/level'): |
117 |
debug_level = configRegistry.get('directory/manager/cmd/debug/level', 1) |
125 |
debug_level=configRegistry['directory/manager/cmd/debug/level'] |
118 |
ud.set_level(ud.ADMIN, int(debug_level)) |
126 |
else: |
119 |
ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] forked to background' % os.getpid()) |
127 |
debug_level=1 |
|
|
128 |
univention.debug.set_level(univention.debug.ADMIN, int(debug_level)) |
129 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] forked to background' % os.getpid()) |
130 |
|
120 |
|
131 |
try: |
121 |
try: |
132 |
os.mkdir(socket_dir) |
122 |
os.mkdir(socket_dir) |
133 |
os.chmod(socket_dir, 0700) |
123 |
os.chmod(socket_dir, 0700) |
134 |
except: |
124 |
except: |
135 |
print 'E: Socket directory exists (%s)' % socket_dir |
125 |
print >> sys.stderr, 'E: socket directory exists (%s)' % socket_dir |
136 |
|
126 |
|
137 |
if configRegistry.has_key('directory/manager/cmd/timeout'): |
127 |
timeout = configRegistry.get('directory/manager/cmd/timeout') |
138 |
timeout=configRegistry['directory/manager/cmd/timeout'] |
128 |
if timeout: |
139 |
if int(timeout) > 2147483647: |
129 |
if int(timeout) > 2147483647: |
140 |
timeout=2147483647 |
130 |
timeout = 2147483647 |
141 |
else: |
131 |
else: |
142 |
timeout=300 |
132 |
timeout = 300 |
143 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.WARN, 'daemon [%s] baseconfig key directory/manager/cmd/timeout not set, setting to default (%s seconds)' % (os.getpid(), timeout)) |
133 |
ud.debug(ud.ADMIN, ud.WARN, 'daemon [%s] baseconfig key directory/manager/cmd/timeout not set, setting to default (%s seconds)' % (os.getpid(), timeout)) |
|
|
134 |
|
144 |
try: |
135 |
try: |
145 |
s=ForkingTCPServer(socket_path, myRequestHandler) |
136 |
sock = ForkingTCPServer(socket_path, MyRequestHandler) |
146 |
os.chmod(socket_path, 0600) |
137 |
os.chmod(socket_path, 0600) |
147 |
except: |
138 |
except: |
148 |
print 'E: Failed creating socket (%s). Daemon stopped.' % socket_path |
139 |
print >> sys.stderr, 'E: Failed creating socket (%s). Daemon stopped.' % socket_path |
149 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'daemon [%s] Failed creating socket (%s). Daemon stopped.' % |
140 |
ud.debug(ud.ADMIN, ud.ERROR, 'daemon [%s] Failed creating socket (%s). Daemon stopped.' % (os.getpid(), socket_filename)) |
150 |
(os.getpid(), socket_filename)) |
|
|
151 |
sys.exit(1) |
141 |
sys.exit(1) |
152 |
|
142 |
|
153 |
#s.listen(2) |
143 |
#sock.listen(2) |
154 |
try: |
144 |
try: |
155 |
runfile=open('%s.run' % socket_path, 'w') |
145 |
runfile = open(runfilename, 'w') |
|
|
146 |
runfile.write(str(os.getpid())) |
147 |
runfile.close() |
156 |
except IOError: |
148 |
except IOError: |
157 |
print 'E: Can`t write runfile' |
149 |
print >> sys.stderr, 'E: Can`t write runfile' |
158 |
|
150 |
|
159 |
runfile.write(str(os.getpid())) |
|
|
160 |
runfile.close() |
161 |
try: |
151 |
try: |
162 |
while 1: |
152 |
while True: |
163 |
input=[] |
153 |
rlist, _wlist, _xlist = select([sock], [], [], float(timeout)) |
164 |
output=[] |
154 |
for handler in rlist: |
165 |
exc=[] |
|
|
166 |
input, output, exc = select.select([s],[],[],float(timeout)) |
167 |
for handler in input: |
168 |
handler.handle_request() |
155 |
handler.handle_request() |
169 |
if not input: |
156 |
if not rlist: |
170 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] stopped after %s seconds idle' % (os.getpid(), timeout)) |
157 |
ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] stopped after %s seconds idle' % (os.getpid(), timeout)) |
171 |
sys.exit(0) |
158 |
sys.exit(0) |
172 |
|
159 |
|
173 |
finally: |
160 |
finally: |
174 |
os.unlink(socket_path) |
161 |
os.unlink(socket_path) |
175 |
os.unlink('%s.run' % socket_path) |
162 |
os.unlink(runfilename) |
176 |
os.rmdir(socket_dir) |
163 |
os.rmdir(socket_dir) |
177 |
univention.debug.exit() |
164 |
ud.exit() |
178 |
|
165 |
|
179 |
|
166 |
|
180 |
def doit(sarglist, conn): |
167 |
def doit(sarglist, conn): |
|
|
168 |
"""Process single UDM request.""" |
181 |
|
169 |
|
182 |
def sendMessage(output): |
170 |
def send_message(output): |
183 |
back=u'' |
171 |
"""Send answer back.""" |
184 |
back=repr(output) |
172 |
back = repr(output) |
185 |
conn.send(back+'\0') |
173 |
conn.send(back + '\0') |
186 |
conn.close() |
174 |
conn.close() |
187 |
|
175 |
|
188 |
global logfile |
176 |
global logfile |
189 |
arglist=eval(sarglist) |
177 |
arglist = eval(sarglist) |
190 |
|
178 |
|
191 |
l=0 |
179 |
next_is_logfile = False |
192 |
b=0 |
180 |
secret = False |
193 |
h=0 |
181 |
show_help = False |
194 |
lsf=1 |
182 |
oldlogfile = logfile |
195 |
oldlogfile=logfile |
183 |
for arg in arglist: |
196 |
for i in arglist: |
184 |
if next_is_logfile == 1: |
197 |
if l == 1: |
185 |
logfile = arg |
198 |
logfile=i |
186 |
next_is_logfile = False |
199 |
l=0 |
187 |
continue |
200 |
if i[:9] == '--logfile': |
188 |
if arg.startswith('--logfile='): |
201 |
if len(i) > 10 and i[9] == "=": |
189 |
logfile = arg[len('--logfile='):] |
202 |
logfile=i[10:] |
190 |
elif arg.startswith('--logfile'): |
203 |
else: |
191 |
next_is_logfile = True |
204 |
l=1 |
192 |
secret |= arg == '--binddn' |
205 |
if i[:8] == '--binddn': |
193 |
show_help |= arg in ('--help', '-h', '-?', '--version') |
206 |
b=1 |
194 |
|
207 |
if i[:6] == '--help': |
195 |
if not secret: |
208 |
h=1 |
196 |
for filename in ('/etc/ldap.secret', '/etc/machine.secret'): |
209 |
if i[:2] == '-h': |
|
|
210 |
h=1 |
211 |
if i[:2] == '-?': |
212 |
h=1 |
213 |
if i[:9] == '--version': |
214 |
h=1 |
215 |
|
216 |
if b == 0: |
217 |
try: |
218 |
ls=open('/etc/ldap.secret', 'r') |
219 |
except IOError: |
220 |
try: |
197 |
try: |
221 |
ls=open('/etc/machine.secret', 'r') |
198 |
open(filename, 'r').close() |
|
|
199 |
secret = True |
200 |
break |
222 |
except IOError: |
201 |
except IOError: |
223 |
lsf=0 |
202 |
continue |
224 |
if h == 0: |
203 |
else: |
225 |
sendMessage(["E: Permission denied, try --logfile, --binddn and --bindpwd"]) |
204 |
if not show_help: |
226 |
sys.exit(1) |
205 |
send_message(["E: Permission denied, try --logfile, --binddn and --bindpwd"]) |
|
|
206 |
sys.exit(1) |
227 |
|
207 |
|
228 |
if logfile!=oldlogfile: |
208 |
if logfile != oldlogfile: |
229 |
univention.debug.exit() |
209 |
ud.exit() |
230 |
univention.debug.init(logfile, 1, 0) |
210 |
ud.init(logfile, ud.FLUSH, ud.NO_FUNCTION) |
231 |
|
211 |
|
232 |
cmdfile=os.path.basename(arglist[0]) |
212 |
cmdfile = os.path.basename(arglist[0]) |
233 |
if cmdfile == 'univention-admin' or cmdfile == 'univention-directory-manager' or cmdfile == 'udm': |
213 |
try: |
234 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-directory-manager' % (os.getppid(), os.getpid())) |
214 |
if cmdfile in ('univention-admin', 'univention-directory-manager', 'udm'): |
235 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
215 |
ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-directory-manager' % (os.getppid(), os.getpid())) |
236 |
try: |
216 |
ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
237 |
output = univention.admincli.admin.doit(arglist) |
217 |
output = univention.admincli.admin.doit(arglist) |
238 |
except: |
218 |
elif cmdfile == 'univention-passwd': |
239 |
info = sys.exc_info() |
219 |
ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-passwd' % (os.getppid(), os.getpid())) |
240 |
output = apply(traceback.format_exception, info) |
220 |
ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
241 |
output = [line[:-1] for line in output] |
|
|
242 |
output.append("OPERATION FAILED") |
243 |
|
244 |
elif cmdfile == 'univention-passwd': |
245 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-passwd' % (os.getppid(), os.getpid())) |
246 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
247 |
try: |
248 |
output = univention.admincli.passwd.doit(arglist) |
221 |
output = univention.admincli.passwd.doit(arglist) |
249 |
except: |
222 |
elif cmdfile == 'univention-license-check': |
250 |
info = sys.exc_info() |
223 |
if licenseImportError: |
251 |
output = apply(traceback.format_exception, info) |
224 |
output = ['The license check is disabled. You are using the GPL version without any support or maintenance by Univention.'] |
252 |
output = [line[:-1] for line in output] |
225 |
else: |
253 |
output.append("OPERATION FAILED") |
226 |
ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-license-check' % (os.getppid(), os.getpid())) |
254 |
elif cmdfile == 'univention-license-check': |
227 |
ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
255 |
if licenseImportError: |
|
|
256 |
output=['The license check is disabled. You are using the GPL version without any support or maintenance by Univention.'] |
257 |
else: |
258 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-license-check' % (os.getppid(), os.getpid())) |
259 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
260 |
try: |
261 |
output = univention.admincli.license_check.doit(arglist) |
228 |
output = univention.admincli.license_check.doit(arglist) |
262 |
except: |
229 |
else: |
263 |
info = sys.exc_info() |
230 |
ud.debug(ud.ADMIN, ud.PROCESS, 'daemon [%s] [%s] Calling univention-adduser' % (os.getppid(), os.getpid())) |
264 |
output = apply(traceback.format_exception, info) |
231 |
ud.debug(ud.ADMIN, ud.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
265 |
output = [line[:-1] for line in output] |
|
|
266 |
output.append("OPERATION FAILED") |
267 |
else: |
268 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.PROCESS, 'daemon [%s] [%s] Calling univention-adduser' % (os.getppid(), os.getpid())) |
269 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.ALL, 'daemon [%s] [%s] arglist: %s' % (os.getppid(), os.getpid(), arglist)) |
270 |
try: |
271 |
output = univention.admincli.adduser.doit(arglist) |
232 |
output = univention.admincli.adduser.doit(arglist) |
272 |
except: |
233 |
except: |
273 |
info = sys.exc_info() |
234 |
ext, exv, extb = sys.exc_info() |
274 |
output = apply(traceback.format_exception, info) |
235 |
output = traceback.format_exception(ext, exv, extb) |
275 |
output = [line[:-1] for line in output] |
236 |
output = [line[:-1] for line in output] |
276 |
output.append("OPERATION FAILED") |
237 |
output.append("OPERATION FAILED") |
277 |
|
238 |
|
278 |
sendMessage(output) |
239 |
send_message(output) |
279 |
|
240 |
|
280 |
if h == 1 and b == 0 and lsf == 0: |
241 |
if show_help and not secret: |
281 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'daemon [%s] [%s] stopped, because User has no read/write permissions' % (os.getppid(), os.getpid())) |
242 |
ud.debug(ud.ADMIN, ud.INFO, 'daemon [%s] [%s] stopped, because User has no read/write permissions' % (os.getppid(), os.getpid())) |
282 |
sys.exit(0) |
243 |
sys.exit(0) |
283 |
|
244 |
|
284 |
|
245 |
|
285 |
if __name__ == "__main__": |
246 |
if __name__ == "__main__": |
286 |
pid = os.fork() |
247 |
pid = os.fork() |
287 |
if not pid: |
248 |
if pid == 0: # child |
288 |
os.setsid() |
249 |
os.setsid() |
289 |
main() |
250 |
main() |
290 |
sys.exit(0) |
251 |
sys.exit(0) |
291 |
else: |
252 |
else: # parent |
292 |
os.waitpid(pid,os.P_NOWAIT) |
253 |
os.waitpid(pid, os.P_NOWAIT) |