Branch '389-ds-base-1.2.8' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/windows_connection.c | 3 ++-
ldap/servers/slapd/auth.c | 6 +++++-
2 files changed, 7 insertions(+), 2 deletions(-)
New commits:
commit 8a15fd460396e7d04a7907d4948493afba2b8083
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu Feb 10 15:23:20 2011 -0700
Bug 676689 - crash while adding a new user to be synced to windows
https://bugzilla.redhat.com/show_bug.cgi?id=676689
Resolves: bug 676689
Bug Description: crash while adding a new user to be synced to windows
Reviewed by: nkinder (Thanks!)
Branch: 389-ds-base-1.2.8
Fix Description: The OpenLDAP ldap_next_entry() function will assert and
abort if passed a NULL message. Mozldap ldap_next_entry() will just return
NULL. Fix the server to not pass NULL to ldap_next_entry().
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 82b362176a8874ace0fd53e69ca6838d33a4881a)
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index f0b8237..50c2abf 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -688,7 +688,8 @@ windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter,
/* See if there are any more entries : if so then that's an error
* but we still need to get them to avoid gumming up the connection
*/
- while (NULL != ( message = ldap_next_entry(conn->ld,message))) ;
+ /* have to check message first - cannot pass a NULL message */
+ while (message && (NULL != ( message = ldap_next_entry(conn->ld,message)))) ;
return_value = CONN_OPERATION_SUCCESS;
}
else if (IS_DISCONNECT_ERROR(ldap_rc))
diff --git a/ldap/servers/slapd/auth.c b/ldap/servers/slapd/auth.c
index 4b56e5e..2c25483 100644
--- a/ldap/servers/slapd/auth.c
+++ b/ldap/servers/slapd/auth.c
@@ -186,7 +186,11 @@ slapu_next_entry( LDAP* ld, LDAPMessage* msg )
{
Slapi_Entry** entry = (Slapi_Entry**)msg;
if (ld != internal_ld) {
- return ldap_next_entry (ld, msg);
+ if (msg) {
+ return ldap_next_entry (ld, msg);
+ } else {
+ return NULL;
+ }
}
if (entry && *entry && *++entry) {
return (LDAPMessage*)entry;
13 years, 3 months
ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/windows_connection.c | 3 ++-
ldap/servers/slapd/auth.c | 6 +++++-
2 files changed, 7 insertions(+), 2 deletions(-)
New commits:
commit 82b362176a8874ace0fd53e69ca6838d33a4881a
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu Feb 10 15:23:20 2011 -0700
Bug 676689 - crash while adding a new user to be synced to windows
https://bugzilla.redhat.com/show_bug.cgi?id=676689
Resolves: bug 676689
Bug Description: crash while adding a new user to be synced to windows
Reviewed by: nkinder (Thanks!)
Branch: master
Fix Description: The OpenLDAP ldap_next_entry() function will assert and
abort if passed a NULL message. Mozldap ldap_next_entry() will just return
NULL. Fix the server to not pass NULL to ldap_next_entry().
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index f0b8237..50c2abf 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -688,7 +688,8 @@ windows_search_entry_ext(Repl_Connection *conn, char* searchbase, char *filter,
/* See if there are any more entries : if so then that's an error
* but we still need to get them to avoid gumming up the connection
*/
- while (NULL != ( message = ldap_next_entry(conn->ld,message))) ;
+ /* have to check message first - cannot pass a NULL message */
+ while (message && (NULL != ( message = ldap_next_entry(conn->ld,message)))) ;
return_value = CONN_OPERATION_SUCCESS;
}
else if (IS_DISCONNECT_ERROR(ldap_rc))
diff --git a/ldap/servers/slapd/auth.c b/ldap/servers/slapd/auth.c
index 4b56e5e..2c25483 100644
--- a/ldap/servers/slapd/auth.c
+++ b/ldap/servers/slapd/auth.c
@@ -186,7 +186,11 @@ slapu_next_entry( LDAP* ld, LDAPMessage* msg )
{
Slapi_Entry** entry = (Slapi_Entry**)msg;
if (ld != internal_ld) {
- return ldap_next_entry (ld, msg);
+ if (msg) {
+ return ldap_next_entry (ld, msg);
+ } else {
+ return NULL;
+ }
}
if (entry && *entry && *++entry) {
return (LDAPMessage*)entry;
13 years, 3 months
Branch '389-ds-base-1.2.8' - ldap/servers
by Noriko Hosoi
ldap/servers/slapd/main.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
New commits:
commit 96bb64a3fdf628c2ed5cb5ce2fbfda0fd1fd37d9
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Feb 8 15:56:57 2011 -0800
Bug 604881 - admin server log files have incorrect permissions/ownerships
https://bugzilla.redhat.com/show_bug.cgi?id=604881
Description: Log files generated in the server's startup time has
the server's owner (nsslapd-localuser) for the owner and the group
who starts the server (ordinarily, root). Once the server goes
into the daemon stage, new log files are owned by owner: nsslapd-
localuser and group: the local user's primary group. The latter
is the correct ownership of the log files.
This patch sets the correct ownership to the files generated in
the server's startup time, as well.
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 21d78e4..059cf33 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -218,7 +218,7 @@ extern void collation_init();
*/
static void
-chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
+chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn, PRBool both)
{
PRDir *dir;
PRDirEntry *entry;
@@ -247,7 +247,7 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL )
{
PR_snprintf(file,MAXPATHLEN+1,"%s/%s",log,entry->name);
- slapd_chown_if_not_owner( file, pw->pw_uid, -1 );
+ slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 );
}
PR_CloseDir( dir );
}
@@ -290,19 +290,19 @@ fix_ownership()
/* config directory needs to be owned by the local user */
if (slapdFrontendConfig->configdir) {
- chown_dir_files(slapdFrontendConfig->configdir, pw, PR_FALSE);
+ chown_dir_files(slapdFrontendConfig->configdir, pw, PR_FALSE, PR_FALSE);
}
/* do access log file, if any */
if (slapdFrontendConfig->accesslog) {
- chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE, PR_TRUE);
}
/* do audit log file, if any */
if (slapdFrontendConfig->auditlog) {
- chown_dir_files(slapdFrontendConfig->auditlog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->auditlog, pw, PR_TRUE, PR_TRUE);
}
/* do error log file, if any */
if (slapdFrontendConfig->errorlog) {
- chown_dir_files(slapdFrontendConfig->errorlog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->errorlog, pw, PR_TRUE, PR_TRUE);
}
}
#endif
13 years, 3 months
admserv/newinst
by Noriko Hosoi
admserv/newinst/src/AdminServer.pm.in | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
New commits:
commit a997fc5610de4acde28043a4711004be57a96c33
Author: Noriko Hosoi <nhosoi(a)jiji.usersys.redhat.com>
Date: Thu Feb 10 14:05:14 2011 -0800
Bug 604881 - admin server log files have incorrect permissions/ownerships
https://bugzilla.redhat.com/show_bug.cgi?id=604881
Description: Log files first generated by the Admin Server/Apache
has the owner (root, root), but the log files created later via
Console/CGI are owned by the Admin User/Group (e.g., nobody, nobody).
To make them consistent, this patch modifies the install script to
call chown to change the owner to the original log files.
diff --git a/admserv/newinst/src/AdminServer.pm.in b/admserv/newinst/src/AdminServer.pm.in
index 1293a96..5f235c9 100644
--- a/admserv/newinst/src/AdminServer.pm.in
+++ b/admserv/newinst/src/AdminServer.pm.in
@@ -542,6 +542,22 @@ sub createAdminServer {
return 0;
}
+ # Force to make log files owned by admin user and group
+ # to maintain consistency with the log files created via CGI/Console
+ my $uid = getpwnam $setup->{inf}->{admin}->{SysUser};
+ my $gid = getgrnam $setup->{inf}->{General}->{SuiteSpotGroup};
+ # chown log files appropriately
+ for (glob("$logdir/*")) {
+ $! = 0; # clear errno
+ debug(1, "Changing the owner of $_ to \($uid, $gid\)\n");
+ chown $uid, $gid, $_;
+ if ($!) {
+ $setup->msg($FATAL, 'error_chowning_file', $_,
+ $admConf->{sysuser}, $!);
+ return 0;
+ }
+ }
+
if ($reconfig) {
$setup->msg('end_reconfig_adminserver');
} else {
13 years, 3 months
ldap/servers
by Noriko Hosoi
ldap/servers/slapd/main.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
New commits:
commit 513e5a83ff806e9dcfa9b32287e2ce7b6ff95ddf
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Feb 8 15:56:57 2011 -0800
Bug 604881 - admin server log files have incorrect permissions/ownerships
https://bugzilla.redhat.com/show_bug.cgi?id=604881
Description: Log files generated in the server's startup time has
the server's owner (nsslapd-localuser) for the owner and the group
who starts the server (ordinarily, root). Once the server goes
into the daemon stage, new log files are owned by owner: nsslapd-
localuser and group: the local user's primary group. The latter
is the correct ownership of the log files.
This patch sets the correct ownership to the files generated in
the server's startup time, as well.
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index 21d78e4..059cf33 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -218,7 +218,7 @@ extern void collation_init();
*/
static void
-chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
+chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn, PRBool both)
{
PRDir *dir;
PRDirEntry *entry;
@@ -247,7 +247,7 @@ chown_dir_files(char *name, struct passwd *pw, PRBool strip_fn)
while( (entry = PR_ReadDir(dir , PR_SKIP_BOTH )) !=NULL )
{
PR_snprintf(file,MAXPATHLEN+1,"%s/%s",log,entry->name);
- slapd_chown_if_not_owner( file, pw->pw_uid, -1 );
+ slapd_chown_if_not_owner( file, pw->pw_uid, both?pw->pw_gid:-1 );
}
PR_CloseDir( dir );
}
@@ -290,19 +290,19 @@ fix_ownership()
/* config directory needs to be owned by the local user */
if (slapdFrontendConfig->configdir) {
- chown_dir_files(slapdFrontendConfig->configdir, pw, PR_FALSE);
+ chown_dir_files(slapdFrontendConfig->configdir, pw, PR_FALSE, PR_FALSE);
}
/* do access log file, if any */
if (slapdFrontendConfig->accesslog) {
- chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->accesslog, pw, PR_TRUE, PR_TRUE);
}
/* do audit log file, if any */
if (slapdFrontendConfig->auditlog) {
- chown_dir_files(slapdFrontendConfig->auditlog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->auditlog, pw, PR_TRUE, PR_TRUE);
}
/* do error log file, if any */
if (slapdFrontendConfig->errorlog) {
- chown_dir_files(slapdFrontendConfig->errorlog, pw, PR_TRUE);
+ chown_dir_files(slapdFrontendConfig->errorlog, pw, PR_TRUE, PR_TRUE);
}
}
#endif
13 years, 3 months
Branch '389-ds-base-1.2.8' - ldap/admin
by Richard Allen Megginson
ldap/admin/src/scripts/ds-logpipe.py | 136 ++++++++++++++++++++++++-----------
1 file changed, 96 insertions(+), 40 deletions(-)
New commits:
commit ceec7ba4e3b9d8baadf2a34591658484606fab9b
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu Feb 3 18:42:37 2011 -0700
Bug 668385 - DS pipe log script is executed as many times as the dirsrv service is restarted
https://bugzilla.redhat.com/show_bug.cgi?id=668385
Resolves: bug 668385
Bug Description: DS pipe log script is executed as many times as the dirsrv service is restarted
Reviewed by: nkinder (Thanks!)
Branch: 389-ds-base-1.2.8
Fix Description: The main thing was adding a pid file for the script itself,
so it can know if it is running or not. This is the new '-i' argument.
The other tricky part was figuring out, when reading the pipe, it is hard to
know if the server has really exited or not, and therefore, if the script
can exit. When the server is starting up, when it daemonizes, it will close
and reopen the log file descriptors. We can detect this as reading just
an eof (line == None) from the pipe and nothing else. In this case, we
can just reopen the log.
When we open the log file, if reading from a server, we always set a timer
because the open will block until something writes to the pipe. However,
readline() will always return and will never block. Even at eof, if the
other side has closed the pipe, readline() will just return None.
The documentation on the wiki has been updated with the new information
about how to set up the init scripts to use the logpipe.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
(cherry picked from commit 1132e09752c8f9aba7a963bfc91a8941000012ca)
diff --git a/ldap/admin/src/scripts/ds-logpipe.py b/ldap/admin/src/scripts/ds-logpipe.py
index 4a6053f..6c448f1 100644
--- a/ldap/admin/src/scripts/ds-logpipe.py
+++ b/ldap/admin/src/scripts/ds-logpipe.py
@@ -16,6 +16,7 @@ S_IFIFO = 0010000
buffer = [] # default circular buffer used by default plugin
totallines = 0
logfname = "" # name of log pipe
+debug = False
# default plugin just keeps a circular buffer
def defaultplugin(line):
@@ -39,10 +40,17 @@ plgpostfuncs = [] # list of post plugin funcs
def finish():
for postfunc in plgpostfuncs: postfunc()
+ if options.scriptpidfile: os.unlink(options.scriptpidfile)
sys.exit(0)
def sighandler(signum, frame):
- if signum != signal.SIGHUP: finish()
+ if signum != signal.SIGHUP:
+ signal.signal(signal.SIGHUP, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ #signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ signal.signal(signal.SIGALRM, signal.SIG_DFL)
+ finish()
else: printbuffer()
def isvalidpluginfile(plg):
@@ -115,7 +123,8 @@ def parse_plugins(parser, options, args):
else:
newargs.append(arg)
if prefunc:
- print 'Calling "pre" function in', plgfile
+ if debug:
+ print 'Calling "pre" function in', plgfile
if not prefunc(bvals):
parser.error('the "pre" function in %s returned an error' % plgfile)
args = newargs
@@ -128,9 +137,6 @@ def open_pipe(logfname):
while not opencompleted:
try:
logf = open(logfname, 'r') # blocks until there is some input
- # set pipe to non-blocking
-# oldflags = fcntl.fcntl(logf, fcntl.F_GETFL)
-# fcntl.fcntl(logf, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
opencompleted = True
except IOError, e:
if e.errno == errno.EINTR:
@@ -139,30 +145,60 @@ def open_pipe(logfname):
raise Exception, "%s [%d]" % (e.strerror, e.errno)
return logf
-def get_server_pid(serverpidfile, servertimeout):
- endtime = int(time.time()) + servertimeout
- serverpid = 0
- if serverpidfile:
+def is_proc_alive(procpid):
+ retval = False
+ try:
+ retval = os.path.exists("/proc/%d" % procpid)
+ except IOError, e:
+ if e.errno != errno.ENOENT: # may not exist yet - that's ok
+ # otherwise, probably permissions or other badness
+ raise Exception, "could not open file %s - %s [%d]" % (procfile, e.strerror, e.errno)
+ # using /proc/pid failed, try kill
+ if not retval:
+ try:
+ os.kill(procpid, 0) # sig 0 is a "ping"
+ retval = True # if we got here, proc exists
+ except OSError, e:
+ pass # no such process, or EPERM/EACCES
+ return retval
+
+def get_pid_from_file(pidfile):
+ procpid = 0
+ if pidfile:
line = None
try:
- spfd = open(serverpidfile, 'r')
- line = spfd.readline()
- spfd.close()
+ pfd = open(pidfile, 'r')
+ line = pfd.readline()
+ pfd.close()
except IOError, e:
if e.errno != errno.ENOENT: # may not exist yet - that's ok
- raise Exception, "%s [%d]" % (e.strerror, e.errno)
+ # otherwise, probably permissions or other badness
+ raise Exception, "Could not read pid from file %s - %s [%d]" % (pidfile, e.strerror, e.errno)
if line:
- serverpid = int(line)
- return serverpid
+ procpid = int(line)
+ return procpid
-def is_server_alive(serverpid):
- retval = False
+def write_pid_file(pidfile):
try:
- os.kill(serverpid, 0) # sig 0 is a "ping"
- retval = True
- except OSError, e:
- pass # no such process, or EPERM/EACCES
- return retval
+ pfd = open(pidfile, 'w')
+ pfd.write("%d\n" % os.getpid())
+ pfd.close()
+ except IOError, e:
+ raise Exception, "Could not write pid to file %s - %s [%d]" % (pidfile, e.strerror, e.errno)
+
+def handle_script_pidfile(scriptpidfile):
+ scriptpid = get_pid_from_file(scriptpidfile)
+ # 0 if no file or no pid or error
+ if scriptpid and is_proc_alive(scriptpid):
+ # already running
+ if debug:
+ print "Script is already running: process id %d" % scriptpid
+ return False
+ else:
+ # either process is not running or no file
+ # write our pid to the file
+ write_pid_file(scriptpidfile)
+ return True
def read_and_process_line(logf, plgfuncs):
line = None
@@ -181,7 +217,7 @@ def read_and_process_line(logf, plgfuncs):
for plgfunc in plgfuncs:
if not plgfunc(line):
print "Aborting processing due to function %s.%s" % (plgfunc.__module__, plgfunc.__name__)
- finish()
+ finish() # this will exit the process
done = True
break
else: # EOF
@@ -206,6 +242,8 @@ def parse_options():
help="process id of server to monitor", default=0)
parser.add_option("-u", "--user", type='string', dest='user',
help='name of user to set effective uid to')
+ parser.add_option("-i", "--scriptpidfile", type='string', dest='scriptpidfile',
+ help='name of file containing the pid of this script')
options, args = parser.parse_args()
@@ -220,6 +258,8 @@ def parse_options():
options, logfname = parse_options()
+if options.debug: debug = True
+
if len(plgfuncs) == 0:
plgfuncs.append(defaultplugin)
if len(plgpostfuncs) == 0:
@@ -231,28 +271,36 @@ if options.user:
userid = pwd.getpwnam(options.user)[2]
os.seteuid(userid)
+if options.scriptpidfile:
+ if not handle_script_pidfile(options.scriptpidfile):
+ options.scriptpidfile = None
+ sys.exit(1)
+
serverpid = options.serverpid
if serverpid:
- if not is_server_alive(serverpid):
+ if not is_proc_alive(serverpid):
print "Server pid [%d] is not alive - exiting" % serverpid
sys.exit(1)
try:
if os.stat(logfname).st_mode & S_IFIFO:
- print "Using existing log pipe", logfname
+ if debug:
+ print "Using existing log pipe", logfname
else:
print "Error:", logfname, "exists and is not a log pipe"
print "use a filename other than", logfname
sys.exit(1)
except OSError, e:
if e.errno == errno.ENOENT:
- print "Creating log pipe", logfname
+ if debug:
+ print "Creating log pipe", logfname
os.mkfifo(logfname)
os.chmod(logfname, 0600)
else:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
-print "Listening to log pipe", logfname, "number of lines", maxlines
+if debug:
+ print "Listening to log pipe", logfname, "number of lines", maxlines
# set up our signal handlers
signal.signal(signal.SIGHUP, sighandler)
@@ -273,13 +321,15 @@ while not done:
logf = open_pipe(logfname)
if serverpid:
- if not is_server_alive(serverpid):
- print "Server pid [%d] is not alive - exiting" % serverpid
- sys.exit(1)
+ if not is_proc_alive(serverpid):
+ done = True
+ if debug:
+ print "Server pid [%d] is not alive - exiting" % serverpid
else: # cancel the timer
signal.alarm(0) # cancel timer - got pid
innerdone = False
+ lines = 0
while not innerdone and not done:
# read and process the next line in the pipe
# if server exits while we are reading, we will get
@@ -288,9 +338,10 @@ while not done:
# we can get the pid file
innerdone = read_and_process_line(logf, plgfuncs)
if not serverpid and options.serverpidfile:
- serverpid = get_server_pid(options.serverpidfile, options.servertimeout)
+ serverpid = get_pid_from_file(options.serverpidfile)
if serverpid:
signal.alarm(0) # cancel timer - got pid
+ if not innerdone: lines += 1
if logf:
logf.close()
@@ -298,17 +349,22 @@ while not done:
if not done:
if serverpid:
- if not is_server_alive(serverpid):
- print "Server pid [%d] is not alive - exiting" % serverpid
- sys.exit(1)
- else: # the server will sometimes close the log and reopen it
+ if not lines:
+ # the server will sometimes close the log and reopen it
+ # when it does this lines will be 0 - this means we need
+ # immediately attempt to reopen the log pipe and read it
# however, at shutdown, the server will close the log before
- # the process has exited - so is_server_alive will return
+ # the process has exited - so is_proc_alive will return
# true for a short time - if we then attempt to open the
# pipe, the open will hang forever - to avoid this situation
- # we set the alarm again to wake up the open
- signal.alarm(options.servertimeout)
-
- print "log pipe", logfname, "closed - reopening"
+ # we set the alarm again to wake up the open - use a short
+ # timeout so we don't wait a long time if the server
+ # really is exiting
+ signal.alarm(5)
+ else:
+ # pipe closed - usually when server shuts down
+ done = True
+ if not done and debug:
+ print "log pipe", logfname, "closed - reopening - read", totallines, "total lines"
finish()
13 years, 3 months
ldap/admin
by Richard Allen Megginson
ldap/admin/src/scripts/ds-logpipe.py | 136 ++++++++++++++++++++++++-----------
1 file changed, 96 insertions(+), 40 deletions(-)
New commits:
commit 1132e09752c8f9aba7a963bfc91a8941000012ca
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Thu Feb 3 18:42:37 2011 -0700
Bug 668385 - DS pipe log script is executed as many times as the dirsrv service is restarted
https://bugzilla.redhat.com/show_bug.cgi?id=668385
Resolves: bug 668385
Bug Description: DS pipe log script is executed as many times as the dirsrv service is restarted
Reviewed by: nkinder (Thanks!)
Branch: master
Fix Description: The main thing was adding a pid file for the script itself,
so it can know if it is running or not. This is the new '-i' argument.
The other tricky part was figuring out, when reading the pipe, it is hard to
know if the server has really exited or not, and therefore, if the script
can exit. When the server is starting up, when it daemonizes, it will close
and reopen the log file descriptors. We can detect this as reading just
an eof (line == None) from the pipe and nothing else. In this case, we
can just reopen the log.
When we open the log file, if reading from a server, we always set a timer
because the open will block until something writes to the pipe. However,
readline() will always return and will never block. Even at eof, if the
other side has closed the pipe, readline() will just return None.
The documentation on the wiki has been updated with the new information
about how to set up the init scripts to use the logpipe.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/admin/src/scripts/ds-logpipe.py b/ldap/admin/src/scripts/ds-logpipe.py
index 4a6053f..6c448f1 100644
--- a/ldap/admin/src/scripts/ds-logpipe.py
+++ b/ldap/admin/src/scripts/ds-logpipe.py
@@ -16,6 +16,7 @@ S_IFIFO = 0010000
buffer = [] # default circular buffer used by default plugin
totallines = 0
logfname = "" # name of log pipe
+debug = False
# default plugin just keeps a circular buffer
def defaultplugin(line):
@@ -39,10 +40,17 @@ plgpostfuncs = [] # list of post plugin funcs
def finish():
for postfunc in plgpostfuncs: postfunc()
+ if options.scriptpidfile: os.unlink(options.scriptpidfile)
sys.exit(0)
def sighandler(signum, frame):
- if signum != signal.SIGHUP: finish()
+ if signum != signal.SIGHUP:
+ signal.signal(signal.SIGHUP, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ #signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ signal.signal(signal.SIGALRM, signal.SIG_DFL)
+ finish()
else: printbuffer()
def isvalidpluginfile(plg):
@@ -115,7 +123,8 @@ def parse_plugins(parser, options, args):
else:
newargs.append(arg)
if prefunc:
- print 'Calling "pre" function in', plgfile
+ if debug:
+ print 'Calling "pre" function in', plgfile
if not prefunc(bvals):
parser.error('the "pre" function in %s returned an error' % plgfile)
args = newargs
@@ -128,9 +137,6 @@ def open_pipe(logfname):
while not opencompleted:
try:
logf = open(logfname, 'r') # blocks until there is some input
- # set pipe to non-blocking
-# oldflags = fcntl.fcntl(logf, fcntl.F_GETFL)
-# fcntl.fcntl(logf, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
opencompleted = True
except IOError, e:
if e.errno == errno.EINTR:
@@ -139,30 +145,60 @@ def open_pipe(logfname):
raise Exception, "%s [%d]" % (e.strerror, e.errno)
return logf
-def get_server_pid(serverpidfile, servertimeout):
- endtime = int(time.time()) + servertimeout
- serverpid = 0
- if serverpidfile:
+def is_proc_alive(procpid):
+ retval = False
+ try:
+ retval = os.path.exists("/proc/%d" % procpid)
+ except IOError, e:
+ if e.errno != errno.ENOENT: # may not exist yet - that's ok
+ # otherwise, probably permissions or other badness
+ raise Exception, "could not open file %s - %s [%d]" % (procfile, e.strerror, e.errno)
+ # using /proc/pid failed, try kill
+ if not retval:
+ try:
+ os.kill(procpid, 0) # sig 0 is a "ping"
+ retval = True # if we got here, proc exists
+ except OSError, e:
+ pass # no such process, or EPERM/EACCES
+ return retval
+
+def get_pid_from_file(pidfile):
+ procpid = 0
+ if pidfile:
line = None
try:
- spfd = open(serverpidfile, 'r')
- line = spfd.readline()
- spfd.close()
+ pfd = open(pidfile, 'r')
+ line = pfd.readline()
+ pfd.close()
except IOError, e:
if e.errno != errno.ENOENT: # may not exist yet - that's ok
- raise Exception, "%s [%d]" % (e.strerror, e.errno)
+ # otherwise, probably permissions or other badness
+ raise Exception, "Could not read pid from file %s - %s [%d]" % (pidfile, e.strerror, e.errno)
if line:
- serverpid = int(line)
- return serverpid
+ procpid = int(line)
+ return procpid
-def is_server_alive(serverpid):
- retval = False
+def write_pid_file(pidfile):
try:
- os.kill(serverpid, 0) # sig 0 is a "ping"
- retval = True
- except OSError, e:
- pass # no such process, or EPERM/EACCES
- return retval
+ pfd = open(pidfile, 'w')
+ pfd.write("%d\n" % os.getpid())
+ pfd.close()
+ except IOError, e:
+ raise Exception, "Could not write pid to file %s - %s [%d]" % (pidfile, e.strerror, e.errno)
+
+def handle_script_pidfile(scriptpidfile):
+ scriptpid = get_pid_from_file(scriptpidfile)
+ # 0 if no file or no pid or error
+ if scriptpid and is_proc_alive(scriptpid):
+ # already running
+ if debug:
+ print "Script is already running: process id %d" % scriptpid
+ return False
+ else:
+ # either process is not running or no file
+ # write our pid to the file
+ write_pid_file(scriptpidfile)
+ return True
def read_and_process_line(logf, plgfuncs):
line = None
@@ -181,7 +217,7 @@ def read_and_process_line(logf, plgfuncs):
for plgfunc in plgfuncs:
if not plgfunc(line):
print "Aborting processing due to function %s.%s" % (plgfunc.__module__, plgfunc.__name__)
- finish()
+ finish() # this will exit the process
done = True
break
else: # EOF
@@ -206,6 +242,8 @@ def parse_options():
help="process id of server to monitor", default=0)
parser.add_option("-u", "--user", type='string', dest='user',
help='name of user to set effective uid to')
+ parser.add_option("-i", "--scriptpidfile", type='string', dest='scriptpidfile',
+ help='name of file containing the pid of this script')
options, args = parser.parse_args()
@@ -220,6 +258,8 @@ def parse_options():
options, logfname = parse_options()
+if options.debug: debug = True
+
if len(plgfuncs) == 0:
plgfuncs.append(defaultplugin)
if len(plgpostfuncs) == 0:
@@ -231,28 +271,36 @@ if options.user:
userid = pwd.getpwnam(options.user)[2]
os.seteuid(userid)
+if options.scriptpidfile:
+ if not handle_script_pidfile(options.scriptpidfile):
+ options.scriptpidfile = None
+ sys.exit(1)
+
serverpid = options.serverpid
if serverpid:
- if not is_server_alive(serverpid):
+ if not is_proc_alive(serverpid):
print "Server pid [%d] is not alive - exiting" % serverpid
sys.exit(1)
try:
if os.stat(logfname).st_mode & S_IFIFO:
- print "Using existing log pipe", logfname
+ if debug:
+ print "Using existing log pipe", logfname
else:
print "Error:", logfname, "exists and is not a log pipe"
print "use a filename other than", logfname
sys.exit(1)
except OSError, e:
if e.errno == errno.ENOENT:
- print "Creating log pipe", logfname
+ if debug:
+ print "Creating log pipe", logfname
os.mkfifo(logfname)
os.chmod(logfname, 0600)
else:
raise Exception, "%s [%d]" % (e.strerror, e.errno)
-print "Listening to log pipe", logfname, "number of lines", maxlines
+if debug:
+ print "Listening to log pipe", logfname, "number of lines", maxlines
# set up our signal handlers
signal.signal(signal.SIGHUP, sighandler)
@@ -273,13 +321,15 @@ while not done:
logf = open_pipe(logfname)
if serverpid:
- if not is_server_alive(serverpid):
- print "Server pid [%d] is not alive - exiting" % serverpid
- sys.exit(1)
+ if not is_proc_alive(serverpid):
+ done = True
+ if debug:
+ print "Server pid [%d] is not alive - exiting" % serverpid
else: # cancel the timer
signal.alarm(0) # cancel timer - got pid
innerdone = False
+ lines = 0
while not innerdone and not done:
# read and process the next line in the pipe
# if server exits while we are reading, we will get
@@ -288,9 +338,10 @@ while not done:
# we can get the pid file
innerdone = read_and_process_line(logf, plgfuncs)
if not serverpid and options.serverpidfile:
- serverpid = get_server_pid(options.serverpidfile, options.servertimeout)
+ serverpid = get_pid_from_file(options.serverpidfile)
if serverpid:
signal.alarm(0) # cancel timer - got pid
+ if not innerdone: lines += 1
if logf:
logf.close()
@@ -298,17 +349,22 @@ while not done:
if not done:
if serverpid:
- if not is_server_alive(serverpid):
- print "Server pid [%d] is not alive - exiting" % serverpid
- sys.exit(1)
- else: # the server will sometimes close the log and reopen it
+ if not lines:
+ # the server will sometimes close the log and reopen it
+ # when it does this lines will be 0 - this means we need
+ # immediately attempt to reopen the log pipe and read it
# however, at shutdown, the server will close the log before
- # the process has exited - so is_server_alive will return
+ # the process has exited - so is_proc_alive will return
# true for a short time - if we then attempt to open the
# pipe, the open will hang forever - to avoid this situation
- # we set the alarm again to wake up the open
- signal.alarm(options.servertimeout)
-
- print "log pipe", logfname, "closed - reopening"
+ # we set the alarm again to wake up the open - use a short
+ # timeout so we don't wait a long time if the server
+ # really is exiting
+ signal.alarm(5)
+ else:
+ # pipe closed - usually when server shuts down
+ done = True
+ if not done and debug:
+ print "log pipe", logfname, "closed - reopening - read", totallines, "total lines"
finish()
13 years, 3 months
Branch '389-ds-base-1.2.8' - ldap/servers
by Nathan Kinder
ldap/servers/slapd/ldaputil.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
New commits:
commit f0e39fd132c9abf976af1c11044b180e5338fcb7
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Feb 8 14:09:58 2011 -0800
Bug 675853 - dirsrv crash segfault in need_new_pw()
A bind DN with a trailing tab in the RDN can cause ns-slapd to crash.
This is ultimately caused by the function that explodes the bind DN
trimming off the tab character, causing the bind entry to be found
by the backend. The frontend uses different logic to find the
bind entry, which fails to find the entry. This discrepency leads
to a crash.
The fix is to only trim trailing spaces (0x20) from RDN values when
exploding a DN. The DN explode function is an internal function
when built against the OpenLDAP client libs, but we use an external
MozLDAP call when built against MozLDAP. This patch makes us always
use our own internal function regardless of the client libs we are
built against.
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 11fe4fb..34aa12e 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -101,14 +101,12 @@
#include <ldappr.h>
#endif
-#if defined(USE_OPENLDAP)
/* the server depends on the old, deprecated ldap_explode behavior which openldap
- does not support - the use of the mozldap code should be seen as a temporary
- measure which we should remove as we improve our internal DN handling */
+ does not support - the use of the mozldap code should be discouraged as
+ there are issues that mozldap does not handle correctly. */
static char **mozldap_ldap_explode( const char *dn, const int notypes, const int nametype );
static char **mozldap_ldap_explode_dn( const char *dn, const int notypes );
static char **mozldap_ldap_explode_rdn( const char *rdn, const int notypes );
-#endif
#ifdef MEMPOOL_EXPERIMENTAL
void _free_wrapper(void *ptr)
@@ -1094,21 +1092,13 @@ done:
char **
slapi_ldap_explode_rdn(const char *rdn, int notypes)
{
-#if defined(USE_OPENLDAP)
return mozldap_ldap_explode_rdn(rdn, notypes);
-#else
- return ldap_explode_rdn(rdn, notypes);
-#endif
}
char **
slapi_ldap_explode_dn(const char *dn, int notypes)
{
-#if defined(USE_OPENLDAP)
return mozldap_ldap_explode_dn(dn, notypes);
-#else
- return ldap_explode_dn(dn, notypes);
-#endif
}
void
@@ -1992,14 +1982,15 @@ cleanup:
#endif /* HAVE_KRB5 */
-#if defined(USE_OPENLDAP)
-
#define LDAP_DN 1
#define LDAP_RDN 2
#define INQUOTE 1
#define OUTQUOTE 2
+/* We use the following two functions when built against OpenLDAP
+ * or the MozLDAP libs since the MozLDAP ldap_explode_dn() function
+ * does not handle trailing whitespace characters properly. */
static char **
mozldap_ldap_explode( const char *dn, const int notypes, const int nametype )
{
@@ -2101,8 +2092,7 @@ mozldap_ldap_explode( const char *dn, const int notypes, const int nametype )
if ( !endquote ) {
/* trim trailing spaces */
while ( len > 0 &&
- ldap_utf8isspace(
- &rdns[count-1][len-1] )) {
+ (rdns[count-1][len-1] == ' ')) {
--len;
}
}
@@ -2148,4 +2138,3 @@ mozldap_ldap_explode_rdn( const char *rdn, const int notypes )
return( mozldap_ldap_explode( rdn, notypes, LDAP_RDN ) );
}
-#endif /* USE_OPENLDAP */
13 years, 3 months
ldap/servers
by Nathan Kinder
ldap/servers/slapd/ldaputil.c | 23 ++++++-----------------
1 file changed, 6 insertions(+), 17 deletions(-)
New commits:
commit 30cb81261036e1347e2dcb86b801dd89d13a2849
Author: Nathan Kinder <nkinder(a)redhat.com>
Date: Tue Feb 8 14:09:58 2011 -0800
Bug 675853 - dirsrv crash segfault in need_new_pw()
A bind DN with a trailing tab in the RDN can cause ns-slapd to crash.
This is ultimately caused by the function that explodes the bind DN
trimming off the tab character, causing the bind entry to be found
by the backend. The frontend uses different logic to find the
bind entry, which fails to find the entry. This discrepency leads
to a crash.
The fix is to only trim trailing spaces (0x20) from RDN values when
exploding a DN. The DN explode function is an internal function
when built against the OpenLDAP client libs, but we use an external
MozLDAP call when built against MozLDAP. This patch makes us always
use our own internal function regardless of the client libs we are
built against.
diff --git a/ldap/servers/slapd/ldaputil.c b/ldap/servers/slapd/ldaputil.c
index 11fe4fb..34aa12e 100644
--- a/ldap/servers/slapd/ldaputil.c
+++ b/ldap/servers/slapd/ldaputil.c
@@ -101,14 +101,12 @@
#include <ldappr.h>
#endif
-#if defined(USE_OPENLDAP)
/* the server depends on the old, deprecated ldap_explode behavior which openldap
- does not support - the use of the mozldap code should be seen as a temporary
- measure which we should remove as we improve our internal DN handling */
+ does not support - the use of the mozldap code should be discouraged as
+ there are issues that mozldap does not handle correctly. */
static char **mozldap_ldap_explode( const char *dn, const int notypes, const int nametype );
static char **mozldap_ldap_explode_dn( const char *dn, const int notypes );
static char **mozldap_ldap_explode_rdn( const char *rdn, const int notypes );
-#endif
#ifdef MEMPOOL_EXPERIMENTAL
void _free_wrapper(void *ptr)
@@ -1094,21 +1092,13 @@ done:
char **
slapi_ldap_explode_rdn(const char *rdn, int notypes)
{
-#if defined(USE_OPENLDAP)
return mozldap_ldap_explode_rdn(rdn, notypes);
-#else
- return ldap_explode_rdn(rdn, notypes);
-#endif
}
char **
slapi_ldap_explode_dn(const char *dn, int notypes)
{
-#if defined(USE_OPENLDAP)
return mozldap_ldap_explode_dn(dn, notypes);
-#else
- return ldap_explode_dn(dn, notypes);
-#endif
}
void
@@ -1992,14 +1982,15 @@ cleanup:
#endif /* HAVE_KRB5 */
-#if defined(USE_OPENLDAP)
-
#define LDAP_DN 1
#define LDAP_RDN 2
#define INQUOTE 1
#define OUTQUOTE 2
+/* We use the following two functions when built against OpenLDAP
+ * or the MozLDAP libs since the MozLDAP ldap_explode_dn() function
+ * does not handle trailing whitespace characters properly. */
static char **
mozldap_ldap_explode( const char *dn, const int notypes, const int nametype )
{
@@ -2101,8 +2092,7 @@ mozldap_ldap_explode( const char *dn, const int notypes, const int nametype )
if ( !endquote ) {
/* trim trailing spaces */
while ( len > 0 &&
- ldap_utf8isspace(
- &rdns[count-1][len-1] )) {
+ (rdns[count-1][len-1] == ' ')) {
--len;
}
}
@@ -2148,4 +2138,3 @@ mozldap_ldap_explode_rdn( const char *rdn, const int notypes )
return( mozldap_ldap_explode( rdn, notypes, LDAP_RDN ) );
}
-#endif /* USE_OPENLDAP */
13 years, 3 months
console/src/com/netscape/management/client/security KeyCertWizardResource.properties, 1.2, 1.3
by Noriko Hosoi
Author: nhosoi
Update of /cvs/dirsec/console/src/com/netscape/management/client/security
In directory cvs01.phx2.fedoraproject.org:/tmp/cvs-serv3915/src/com/netscape/management/client/security
Modified Files:
KeyCertWizardResource.properties
Log Message:
Description by Ulf Weltman (ulf.weltman(a)hp.com):
The fourth step of the certificate management wizard for both
installing server certificate and CA certificate point to bad URLs.
The resource key for one is using capitalized "Admin" when it
should be lowercase "admin", and the other resource key is missing
a value.
Checking in the patch on behalf of Ulf Weltman (ulf.weltman(a)hp.com).
Index: KeyCertWizardResource.properties
===================================================================
RCS file: /cvs/dirsec/console/src/com/netscape/management/client/security/KeyCertWizardResource.properties,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- KeyCertWizardResource.properties 13 Jun 2007 20:33:09 -0000 1.2
+++ KeyCertWizardResource.properties 8 Feb 2011 19:45:43 -0000 1.3
@@ -115,7 +115,7 @@
#Request submission
-CertRequestSubmissionPage-help=Admin
+CertRequestSubmissionPage-help=admin
CertRequestSubmissionPage-pageTitle=Request Submission
CertRequestSubmissionPage-explain=This certificate request should be submitted to a Certificate Authority (CA) that will process it and issue a certificate.\n\nYou can submit this request manually, either by sending it in an email message to the CA or by submitting it through the CA's web site.
CertRequestSubmissionPage-saveToFileLabel=Save to file
@@ -167,7 +167,7 @@
CertInstallSetTrustPage-purposeLabel=Which of the following tasks should this certificate be trusted?
CertInstallSetTrustPage-trustClientLabel=Accepting connections from clients. (Client Authentication)
CertInstallSetTrustPage-trustServerLabel=Making connections to other servers. (Server Authentication)
-CertInstallSetTrustPage-help
+CertInstallSetTrustPage-help=admin
# Cert Install Cert Name Page
CertInstallCertNamePage-pageTitle=Certificate Type
13 years, 3 months