summaryrefslogtreecommitdiff
path: root/slapd-pivot.py
blob: 704c16e6f333199803b25ae5f09b5c9400dbe0c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python

import sys, os
import getopt, syslog
import pwd, grp

import Backend, Pivot, Config

SCRIPT = "slapd-pivot"
USER = None
GROUP = None
PIDFILE = None

class Log:
	def __init__(self):
		syslog.openlog('slapd-pivot')
	def write(self, string):
		string = string.encode("utf-8", "replace").strip("\n\r")
		if string:
			syslog.syslog(syslog.LOG_WARNING | syslog.LOG_DAEMON, string)
	def flush(self):
		pass


def failure(msg, details = None):
	if details:
		msg += ": " + details
	print >> sys.stderr, "%s: %s" % (SCRIPT, msg)
	sys.exit(1)


def usage():
	print >> sys.stderr, "usage: %s -f config [-d level] [-g group] [-p pidfile] [-u user]" % SCRIPT
	sys.exit(2)


def run_server():
	server = Backend.Server("/tmp/pivot-slapd.sock", Pivot.Database)
	try:
		print >> sys.stderr, "%s starting up..." % SCRIPT
		server.serve_forever()
	except KeyboardInterrupt:
		sys.exit(0)


def drop_privileges():
	global GROUP, USER

	if GROUP:
		try:
			GROUP = int(GROUP)
		except ValueError:
			try:
				GROUP = grp.getgrgid(GROUP)[2]
			except KeyError:
				failure("invalid group: %s" % GROUP)
		os.setegid(GROUP)

	if USER:
		try:
			USER = int(USER)
		except ValueError:
			try:
				USER = pwd.getpwnam(USER)[2]
			except KeyError:
				failure("invalid user: %s" % USER)
		os.seteuid(USER)


def daemon():
	# do the UNIX double-fork magic, see Stevens' "Advanced
	# Programming in the UNIX Environment" for details (ISBN 0201563177)
	try:
		pid = os.fork()
		if pid > 0:
			# exit first parent
			sys.exit(0)
	except OSError, e:
		failure("couldn't fork to daemon", e.strerror)

	# decouple from parent environment
	os.setsid()
	os.umask(0)

	# do second fork
	try:
		pid = os.fork()
		if pid > 0:
			# exit from second parent, print eventual PID before
			if PIDFILE:
				open(PIDFILE,'w').write("%d" % pid)
			sys.exit(0)
	except OSError, e:
		failure("couldn't fork to daemon", e.strerror)

	os.chdir("/")
	sys.stderr = Log()


if __name__ == '__main__':

	daemonize = True
	config = "/usr/local/etc/slapd-pivot.conf"

	try:
		opts, args = getopt.getopt(sys.argv[1:], 'd:f:g:p:u:')
	except getopt.GetoptError:
		usage()

	for (opt, oarg) in opts:
		if opt == "-d":
			try:
				daemonize = False
				level = int(oarg)
				if level >= 4:
					Backend.debug = True
			except:
				failure("invalid debug level", oarg)
		elif opt == '-f':
			config = oarg

		elif opt == '-g':
			GROUP = oarg

		elif opt == '-p':
			PIDFILE = oarg

		elif opt == '-u':
			USER = oarg

	# No extra arguments
	if args:
		usage()

	try:
		# Load up our config file
		Config.load(config)
	except Config.Error, ex:
		failure(str(ex))

	# Change to a user that was specified
	drop_privileges()

	# Become a daemon if requested
	if daemonize:
		daemon()

	# And off we go
	run_server()