systemctl start httpd.service
systemctl enable oddjobd.service
systemctl start oddjobd.service
+systemctl enable pds.service
+systemctl start pds.service
systemctl enable postfix.service
systemctl start postfix.service
+systemctl enable rsyncd.service
+systemctl start rsyncd.service
systemctl enable sssd.service
systemctl start sssd.service
444 postinstall/install-data/etc/ssh/ssh_host_*_key.pub
600 postinstall/install-data/etc/ssh/sshd_config.d/*.conf
600 postinstall/install-data/etc/sssd/sssd.conf
-755 postinstall/install-data/usr/local/bin/*.py
-755 postinstall/install-data/usr/local/bin/*.sh
+755 postinstall/install-data/usr/local/bin/*
755 postinstall/scripts/*.sh
+755 preinstall/scripts/*.sh
# owner file (relative to /c3d)
-root:ssh_keys postinstall/install-data/etc/ssh/ssh_host_*_key
-WSGISocketPrefix run/wsgi
-
<VirtualHost *:80>
ServerName fdc.in.useribm.hu
ServerAdmin siteadmin@useribm.hu
Require all granted
</Directory>
- WSGIDaemonProcess was.80 processes=1 threads=1 maximum-requests=10000 shutdown-timeout=5
- WSGIProcessGroup was.80
- WSGIScriptAlias /passwordchange /var/www/htdocs.80/wsgi/passwordchange.wsgi
+ WSGIDaemonProcess fdc.80
+ WSGIProcessGroup fdc.80
+ WSGIScriptAlias /passwordchange /var/www/wsgi/passwordchange.wsgi
</VirtualHost>
--- /dev/null
+[server]
+address =
+port = 1420
+database = /var/lib/pds/db
+
+[targets]
+count = 2
+
+[target.1]
+format = htdigest
+htdigest realm = webdrive
+method = rsync
+rsync host = store.in.useribm.hu
+rsync module = httpdauth
+rsync file = webdrive.digest
+
+[target.2]
+format = htdigest
+htdigest realm = ceges
+method = rsync
+rsync host = store.in.useribm.hu
+rsync module = httpdauth
+rsync file = ceges.digest
--- /dev/null
+transfer logging = yes
+use chroot = no
+uid = root
+gid = root
+
+[pdsdb]
+ path = /var/lib/pds
+ read only = true
+ hosts allow = 10.228.0.0/16, 2001:1aa1:000a:0424::/64
--- /dev/null
+[Unit]
+Description=Password Distribution Server
+After=NetworkManager.service
+Wants=NetworkManager.service
+
+[Service]
+Type=simple
+ExecStart=/usr/local/bin/pds
+
+[Install]
+WantedBy=multi-user.target
#!/usr/bin/env python
+import os
import ldap
import time
-import email
+import pickle
import smtplib
+import email.policy
+import email.message
-LDAP_URI='ldaps://fds.useribm.hu'
-USERS_BASE='ou=people,dc=user,dc=hu'
+LDAP_URI = 'ldaps://fds.useribm.hu'
+USERS_BASE = 'ou=people,dc=user,dc=hu'
PWD_MAX_AGE = 365 * 24 * 60 * 60
PWD_WARNING_MESSAGE = '''Tisztelt {}!
A jelszavad a céges címtárban (például a fájlszerver eléréshez) le fog járni {} nap múlva.
-Kérlek adj meg új jelszót (a régi megadása után) a https://www.useribm.hu/passwordchange oldalon
+Kérlek adj meg új jelszót (a régi megadása után) a https://www.useribm.hu/passwordchange oldalon.
-Üdvözlettel, Címtár'''
+Üdvözlettel,
+USER Címtár'''
PWD_ERROR_SUBJECT = 'Jelszavad lejárt'
PWD_ERROR_MESSAGE = '''Tisztelt {}!
A jelszavad a céges címtárban (például a fájlszerver eléréshez) lejárt.
-Kérlek adj meg új jelszót (a régi megadása után) a https://www.useribm.hu/passwordchange oldalon
+Kérlek adj meg új jelszót (a régi megadása után) a https://www.useribm.hu/passwordchange oldalon.
-Üdvözlettel, Címtár'''
+Üdvözlettel,
+USER Címtár'''
def send_mail(mail_type, expiration_days, uid, email_address):
- msg = email.message.EmailMessage()
+ msg = email.message.EmailMessage(email.policy.SMTP)
if mail_type == 'WARNING':
- msg.set_content(PWD_WARNING_MESSAGE.format(uid, expiration_days))
- msg['Subject'] = PWD_WARNING_SUBJECT.format(expiration_days)
+ msg.set_content(PWD_WARNING_MESSAGE.format(uid,
+ expiration_days))
+ msg.add_header('Subject',
+ PWD_WARNING_SUBJECT.format(expiration_days))
elif mail_type == 'ERROR':
msg.set_content(PWD_ERROR_MESSAGE.format(uid))
- msg['Subject'] = PWD_ERROR_SUBJECT
+ msg.add_header('Subject', PWD_ERROR_SUBJECT)
elif mail_type == 'CRITICAL':
msg.set_content(PWD_ERROR_MESSAGE.format(uid))
- msg['Subject'] = PWD_ERROR_SUBJECT
+ msg.add_header('Subject', PWD_ERROR_SUBJECT)
else:
msg.set_content('Invalid mail_type value: {}'.format(mail_type))
- msg['Subject'] = 'Invalid mail_type value: {}'.format(mail_type)
+ msg.add_header('Subject',
+ 'Invalid mail_type value: {}'.format(mail_type))
email_address = 'zoltan.felleg@userrendszerhaz.hu'
- msg['From'] = 'dirsrv@useribm.hu'
- msg['To'] = email_address
+ msg.add_header('From', '"USER Címtár" <dirsrv@useribm.hu>')
+ msg.add_header('To', email_address)
+ msg.add_header('Date', time.asctime(time.gmtime()))
srv = smtplib.SMTP()
- srv.connect('mx.in.useribm.hu')
+ srv.connect('mx.in.useribm.hu', 587)
+ srv.ehlo()
srv.send_message(msg)
srv.quit()
'pwdUpdateTime'])
(search_result_type, search_result_data) = ldap_object.result()
- current_timestamp = time.mktime(time.gmtime())
+ current_ts = time.mktime(time.gmtime())
+ valid_users = []
for item in search_result_data:
(dn, values) = item
if ('mail' in values) and ('pwdUpdateTime' in values):
uid = values['uid'][0].decode('utf-8')
email_address = values['mail'][0].decode('utf-8')
pwd_update_time = values['pwdUpdateTime'][0].decode('utf-8')
- pwd_update_timestamp = time.mktime(time.strptime(pwd_update_time, '%Y%m%d%H%M%S%z'))
- expiration_seconds = PWD_MAX_AGE - (current_timestamp - pwd_update_timestamp)
+ pwd_update_ts = time.mktime(time.strptime(pwd_update_time,
+ '%Y%m%d%H%M%S%z'))
+ expiration_seconds = PWD_MAX_AGE - (current_ts - pwd_update_ts)
expiration_days = expiration_seconds / (24 * 60 * 60)
- rounded_expiration_days = int(expiration_days + 0.5)
+ if expiration_days < 0:
+ rounded_expiration_days = int(expiration_days - 0.5)
+ else:
+ rounded_expiration_days = int(expiration_days + 0.5)
+ valid_users.append(uid)
+ #print(uid, rounded_expiration_days)
+ #continue
if rounded_expiration_days in PWD_EXPIRED_DAYS:
send_mail('ERROR', rounded_expiration_days, uid, email_address)
elif rounded_expiration_days in PWD_EXPIRING_DAYS:
send_mail('WARNING', rounded_expiration_days, uid, email_address)
+ #elif uid == 'zfelleg':
+ # send_mail('CRITICAL', rounded_expiration_days, uid, email_address)
--- /dev/null
+#!/usr/bin/env python
+
+
+import os
+import sys
+import base64
+import pickle
+import select
+import signal
+import socket
+import hashlib
+import subprocess
+import configparser
+
+
+class ossh:
+
+ """Operating System Signal Handler.
+
+ Class attributes:
+ None
+
+ Instance attributes:
+ _cfg (private)
+ The configuration.
+
+ Methods:
+ __init__
+ Create an ossh.
+ _shutdown_server (private)
+ Shut down the server.
+
+ """
+
+ def __init__(self):
+ """Create an ossh.
+
+ Parameters:
+ None
+
+ Return value:
+ An ossh.
+
+ Exceptions:
+ all/any
+
+ """
+ self._cfg = configparser.ConfigParser()
+ self._cfg.read('/etc/pds.conf')
+
+ server_cfg = self._cfg['server']
+ self._server_address = server_cfg.get('address', 'localhost')
+ self._server_port = server_cfg.getint('port')
+
+ signal.signal(signal.SIGINT, self._shutdown_server)
+ signal.signal(signal.SIGTERM, self._shutdown_server)
+
+ def _shutdown_server(self, *args):
+ """Shut down the server.
+
+ Parameters:
+ None
+
+ Return value:
+ None
+
+ Exceptions:
+ all/any
+
+ """
+ request_dict = {'request': 'shutdown'}
+ request_bytes = pickle.dumps(request_dict)
+ co = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ co.connect((self._server_address, self._server_port))
+ co.sendall(request_bytes)
+ co.shutdown(socket.SHUT_RDWR)
+ co.close()
+
+class pds():
+
+ """Password Distribution Server.
+
+ Class attributes:
+ None
+
+ Instance attributes:
+ _cfg (private)
+ The configuration.
+ _co (private)
+ The connection object (socket).
+ _db (private)
+ The password database.
+ _db_file_name (private)
+ The (fully qualified) file name of the password database.
+
+ Methods:
+ __init__
+ Create a pds.
+ _shutdown (private)
+ Shut down the pds.
+ run
+ Run the pds.
+
+ """
+
+ def __init__(self):
+ """Create a pds.
+
+ Parameters:
+ None
+
+ Return value:
+ a pds.
+
+ """
+ self._cfg = configparser.ConfigParser()
+ self._cfg.read('/etc/pds.conf')
+
+ self._db_file_name = self._cfg['server']['database']
+ db_file = open(self._db_file_name, 'rb')
+ self._db = pickle.load(db_file)
+ db_file.close()
+
+ self._co = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self._co.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+
+ self._signal_handler = ossh()
+
+ def _change_password(self, request_dict):
+ """Change the password of a user.
+
+ Parameters:
+ request_dict
+ The request.
+
+ Return value:
+ The response.
+
+ """
+ login_name = request_dict['login name']
+ password_b16 = request_dict['password']
+ password_b64 = base64.b16decode(password_b16)
+ password_bytes = base64.b64decode(password_b64)
+ password_string = password_bytes.decode('utf-8')
+ password_dict = {}
+ targets_cfg = self._cfg['targets']
+ target_count = targets_cfg.getint('count')
+ for target_serial in range(target_count):
+ target_section = 'target.{}'.format(target_serial + 1)
+ target_cfg = self._cfg[target_section]
+ target_format = target_cfg.get('format')
+ if target_format != 'htdigest':
+ reason = 'Invalid format {}.'.format(target_format)
+ return {'success': False, 'reason': reason}
+ target_realm = target_cfg.get('htdigest realm')
+ source_string = '{}:{}:{}'.format(login_name,
+ target_realm,
+ password_string)
+ source_bytes = source_string.encode('utf-8')
+ htdigest = hashlib.md5(source_bytes).hexdigest()
+ password_dict[(target_format, target_realm)] = htdigest
+ #md5_digest = hashlib.md5(password_bytes).hexdigest()
+ #sha1_digest = hashlib.sha1(password_bytes).hexdigest()
+ #sha224_digest = hashlib.sha224(password_bytes).hexdigest()
+ #sha256_digest = hashlib.sha256(password_bytes).hexdigest()
+ #sha384_digest = hashlib.sha384(password_bytes).hexdigest()
+ #sha512_digest = hashlib.sha512(password_bytes).hexdigest()
+ #result = subprocess.run(['mkpasswd',
+ # '--method=md5crypt',
+ # password_bytes],
+ # capture_output=True)
+ #salted_md5_digest = result.stdout.decode().strip()
+ #result = subprocess.run(['mkpasswd',
+ # '--method=sha256crypt',
+ # password_bytes],
+ # capture_output=True)
+ #salted_sha256_digest = result.stdout.decode().strip()
+ #result = subprocess.run(['mkpasswd',
+ # '--method=sha512crypt',
+ # password_bytes],
+ # capture_output=True)
+ #salted_sha512_digest = result.stdout.decode().strip()
+ #result = subprocess.run(['mkpasswd',
+ # '--method=yescrypt',
+ # password_bytes],
+ # capture_output=True)
+ #yescrypt_digest = result.stdout.decode().strip()
+
+ self._db[login_name] = password_dict
+ success = self._save_db()
+ if not success:
+ reason = 'Could not save password database.'
+ return {'success': False, 'reason': reason}
+ success = self._notifytargets()
+ if not success:
+ reason = 'Could not notify all targets.'
+ return {'success': False, 'reason': reason}
+ return {'success': True}
+
+ def _expire_password(self, request_dict):
+ """Expire the password of a user.
+
+ Parameters:
+ request_dict
+ The request.
+
+ Return value:
+ None
+
+ """
+ login_name = request_dict['login name']
+ if login_name in self._db:
+ del self._db[login_name]
+ success = self._save_db()
+ if not success:
+ reason = 'Could not save password database.'
+ return {'success': False, 'reason': reason}
+ success = self._notifytargets()
+ if not success:
+ reason = 'Could not notify all targets.'
+ return {'success': False, 'reason': reason}
+ return {'success': True}
+
+ def _notifytargets(self):
+ """Notify targets of the changed/expired passwords.
+
+ Parameters:
+ None
+
+ Return value:
+ None
+
+ """
+ success = True
+ targets_cfg = self._cfg['targets']
+ target_count = targets_cfg.getint('count')
+ for target_serial in range(target_count):
+ target_section = 'target.{}'.format(target_serial + 1)
+ target_cfg = self._cfg[target_section]
+ target_format = target_cfg.get('format')
+ target_method = target_cfg.get('method')
+ if (target_format, target_method) != ('htdigest', 'rsync'):
+ success = False
+ continue
+ target_realm = target_cfg.get('htdigest realm')
+ db_key = (target_format, target_realm)
+ target_host = target_cfg.get('rsync host')
+ target_module = target_cfg.get('rsync module')
+ target_file = target_cfg.get('rsync file')
+ local_file_name = os.path.join('/tmp', target_file)
+ local_file = open(local_file_name, 'wt')
+ digest_lines = []
+ for login_name in sorted(self._db.keys()):
+ if db_key not in self._db[login_name]:
+ success = False
+ continue
+ htdigest = self._db[login_name][db_key]
+ digest_line = '{}:{}:{}{}'.format(login_name,
+ target_realm,
+ htdigest,
+ os.linesep)
+ digest_lines.append(digest_line)
+ local_file.writelines(digest_lines)
+ local_file.close()
+ rsync_target = '{}::{}'.format(target_host, target_module)
+ result = subprocess.run(['rsync',
+ '--archive',
+ local_file_name,
+ rsync_target])
+ if result.returncode != 0:
+ success = False
+ return success
+
+ def _respond(self, client_co, response_dict):
+ """Respond to a client.
+
+ Parameters:
+ client_co
+ The connection object (socket) of the client.
+ response_dict
+ The response.
+
+ Return value:
+ None
+
+ """
+ response_bytes = pickle.dumps(response_dict)
+ client_co.sendall(response_bytes)
+
+ def _save_db(self):
+ """Save the password database.
+
+ Parameters:
+ None
+
+ Return value:
+ success
+
+ """
+ db_file = open(self._db_file_name, 'wb')
+ pickle.dump(self._db, db_file)
+ db_file.close()
+ return True
+
+ def _shutdown(self):
+ """Shut down the pds.
+
+ Parameters:
+ None
+
+ Return value:
+ None
+
+ """
+ self._co.shutdown(socket.SHUT_RDWR)
+ self._co.close()
+ sys.exit()
+
+ def run(self):
+ """Run the pds.
+
+ Parameters:
+ None
+
+ Return value:
+ None
+
+ """
+ server_cfg = self._cfg['server']
+ server_address = server_cfg.get('address')
+ server_port = server_cfg.getint('port')
+ self._co.bind((server_address, server_port))
+ self._co.listen(5)
+ while True:
+ (rfr, rfw, rfx) = select.select([self._co], [], [], 900)
+ if rfr == []:
+ print('no client')
+ sys.stdout.flush()
+ continue
+
+ (client_co, client_address) = self._co.accept()
+ print('Connected by {}'.format(client_address))
+ sys.stdout.flush()
+ request_bytes = client_co.recv(4096)
+ if not request_bytes:
+ print('Disconnected by {}'.format(client_address))
+ sys.stdout.flush()
+ client_co.close()
+ continue
+ request_dict = pickle.loads(request_bytes)
+ print('Received: {}'.format(request_dict))
+ sys.stdout.flush()
+ request = request_dict['request']
+ if request == 'change password':
+ response_dict = self._change_password(request_dict)
+ elif request == 'expire password':
+ response_dict = self._expire_password(request_dict)
+ elif request == 'shutdown':
+ client_co.shutdown(socket.SHUT_RDWR)
+ client_co.close()
+ self._shutdown()
+ self._respond(client_co, response_dict)
+ client_co.shutdown(socket.SHUT_RDWR)
+ client_co.close()
+
+
+if __name__ == '__main__':
+ server = pds()
+ server.run()
</head>
<body>
<form action="passwordchange" method="post">
- <p>Login Name:</p>
- <p><input name="login_name" type="text" /></p>
- <p>Old Password:</p>
- <p><input name="old_password" type="password" /></p>
+ <p>Felhaszálónév:</p>
+ <p><input name="login name" type="text" required="true" /></p>
+ <p>Régi jelszó:</p>
+ <p><input name="old password" type="password" required="true" /></p>
<hr />
- <p>New Password:</p>
- <p><input name="new_password" type="password" /></p>
- <p>New Password Again:</p>
- <p><input name="new_password_again" type="password" /></p>
- <p><input type="submit" value="Change" /></p>
+ <p>Új jelszó:</p>
+ <p><input name="new password" type="password" required="true" /></p>
+ <p>Új jelszó mégegyszer:</p>
+ <p><input name="new password again" type="password" required="true" /></p>
+ <p><input type="submit" value="Változtatás" /></p>
</form>
</body>
</html>
/* Center horizontally*/
text-align: center;
}
+
+hr {
+ width: 25%;
+}
+++ /dev/null
- </body>
-</html>
+++ /dev/null
-import os
-import cgi
-import sys
-import ldap
-import traceback
-
-
-LDAP_URI='ldaps://fds.useribm.hu'
-USERS_BASE='ou=people,dc=user,dc=hu'
-
-
-def password_change_app(environ, start_response):
-
- error_occured = False
-
- field_storage = cgi.FieldStorage(fp=environ['wsgi.input'],
- environ=environ,
- keep_blank_values=True)
-
- uid = field_storage['login_name'].value
- old_password = field_storage['old_password'].value
- new_password = field_storage['new_password'].value
- new_password_again = field_storage['new_password_again'].value
-
- if new_password != new_password_again:
- formatted_traceback = ['NEW_PASSWORD_MISMATCH']
- error_occured = True
-
- if not error_occured:
- try:
- ldap_object = ldap.initialize(LDAP_URI)
- #ldap_object.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
- #ldap_object.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
- except:
- (exc_type, exc_value, exc_traceback) = sys.exc_info()
- formatted_traceback = traceback.format_exception(exc_type,
- exc_value,
- exc_traceback)
- error_occured = True
-
- if not error_occured:
- user_dn=','.join(['uid={}'.format(uid), USERS_BASE])
- try:
- bind_id = ldap_object.simple_bind(user_dn, old_password)
- (bind_result_type, bind_result_data) = ldap_object.result()
- except:
- (exc_type, exc_value, exc_traceback) = sys.exc_info()
- formatted_traceback = traceback.format_exception(exc_type,
- exc_value,
- exc_traceback)
- error_occured = True
-
- if not error_occured:
- try:
- password_change_id = ldap_object.passwd(user_dn,
- old_password,
- new_password)
- (pwd_result_type, pwd_result_data) = ldap_object.result()
- except:
- (exc_type, exc_value, exc_traceback) = sys.exc_info()
- formatted_traceback = traceback.format_exception(exc_type,
- exc_value,
- exc_traceback)
- error_occured = True
-
- prologue_file = open('/var/www/htdocs.80/wsgi/prologue.xhtml', 'r')
- response_prologue = prologue_file.read()
- prologue_file.close()
- response_epilogue = '</body></html>'
- if not error_occured:
- success_text = '<h1>Woohoo, you have successfully changed your password!</h1>'
- response_texts = [response_prologue,
- success_text,
- response_epilogue]
- else:
- response_texts = [response_prologue, '<pre>']
- response_texts.extend(formatted_traceback)
- response_texts.append('</pre>')
- response_texts.append('<p><button onclick="history.back()">Go Back and Try Again</button></p>')
- response_texts.append(response_epilogue)
- response_body = bytes(os.linesep.join(response_texts), 'utf-8')
-
- # HTTP response code and message
- status = '200 OK'
-
- # HTTP headers expected by the client
- # They must be wrapped as a list of tupled pairs:
- # [(Header name, Header value)].
- response_headers = [
- ('Content-Type', 'text/html'),
- ('Content-Length', str(len(response_body)))
- ]
-
- # Send them to the server using the supplied function
- start_response(status, response_headers)
-
- # Return the response body. Notice it is wrapped
- # in a list although it could be any iterable.
- return [response_body]
-
-application = password_change_app
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html>
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Password Change</title>
- <meta http-equiv="content-type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" href="main.css" type="text/css" />
- </head>
- <body>
--- /dev/null
+import os
+import sys
+import ldap
+import base64
+import pickle
+import socket
+import traceback
+import configparser
+import urllib.parse
+
+
+LDAP_URI='ldaps://fds.useribm.hu'
+USERS_BASE='ou=people,dc=user,dc=hu'
+
+html_prologue = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Password Change</title>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <link rel="stylesheet" href="main.css" type="text/css" />
+ </head>
+ <body>"""
+
+html_epilogue = """ </body>
+</html>"""
+
+error_prologue = """ <p>Az alábbi hiba miatt nem sikerült megváltoztatni a jelszavadat.
+ Ha a hibaüzenet <b>utolsó sora</b> mond neked valamit,
+ próbáld meg újra.</p>
+ <p>Ha nem, keresd meg zfelleget.</p>
+ <p>(Akinek persze az lesz az első kérdése, hogy mi volt a
+ hibaüzenet utolsó sora, úgyhogy azt vagy mentsd el/írd le,
+ vagy hagyd nyitva ezt a böngészőablakot.)</p>
+ <pre>"""
+
+error_epilogue = """ </pre>
+ <p><button onclick="history.back()">Újrapróbálkozás</button></p>"""
+
+success_text = """ <h1>Jelszavadat sikeresen megváltoztattad,
+ az új jelszó azonnal érvényes.</h1>"""
+
+
+def password_change_app(environ, start_response):
+
+ error_occured = False
+
+ form_data_bytes = environ['wsgi.input'].read()
+ form_data_text = form_data_bytes.decode()
+ form_data_dict = urllib.parse.parse_qs(form_data_text)
+ #formatted_traceback = ['{}'.format(form_data_dict)]
+ #error_occured = True
+ uid = form_data_dict['login name'][0]
+ old_password = form_data_dict['old password'][0]
+ new_password = form_data_dict['new password'][0]
+ new_password_again = form_data_dict['new password again'][0]
+
+ if new_password != new_password_again:
+ formatted_traceback = ['The (new) passwords do not match.']
+ error_occured = True
+
+ if not error_occured:
+ try:
+ ldap_object = ldap.initialize(LDAP_URI)
+ #ldap_object.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
+ #ldap_object.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
+ except:
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ formatted_traceback = traceback.format_exception(exc_type,
+ exc_value,
+ exc_traceback)
+ error_occured = True
+
+ if not error_occured:
+ user_dn=','.join(['uid={}'.format(uid), USERS_BASE])
+ try:
+ bind_id = ldap_object.simple_bind(user_dn, old_password)
+ (bind_result_type, bind_result_data) = ldap_object.result()
+ except:
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ formatted_traceback = traceback.format_exception(exc_type,
+ exc_value,
+ exc_traceback)
+ error_occured = True
+
+ if not error_occured:
+ try:
+ password_change_id = ldap_object.passwd(user_dn,
+ old_password,
+ new_password)
+ (pwd_result_type, pwd_result_data) = ldap_object.result()
+ except:
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ formatted_traceback = traceback.format_exception(exc_type,
+ exc_value,
+ exc_traceback)
+ error_occured = True
+
+ if not error_occured:
+ try:
+ password_bytes = bytes(new_password, 'utf-8')
+ password_b64 = base64.b64encode(password_bytes)
+ password_b16 = base64.b16encode(password_b64)
+ cfg = configparser.ConfigParser()
+ cfg.read('/etc/pds.conf')
+ server_cfg = cfg['server']
+ server_address = server_cfg.get('address', 'localhost')
+ server_port = server_cfg.getint('port')
+ request_dict = {'request': 'change password',
+ 'login name': uid,
+ 'password': password_b16}
+ request_bytes = pickle.dumps(request_dict)
+ co = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ co.settimeout(3)
+ co.connect((server_address, server_port))
+ co.sendall(request_bytes)
+ response_bytes = co.recv(4096)
+ co.shutdown(socket.SHUT_RDWR)
+ co.close()
+ except:
+ (exc_type, exc_value, exc_traceback) = sys.exc_info()
+ formatted_traceback = traceback.format_exception(exc_type,
+ exc_value,
+ exc_traceback)
+ error_occured = True
+
+ if not error_occured:
+ response_texts = [html_prologue,
+ success_text,
+ html_epilogue]
+ else:
+ response_texts = [html_prologue, error_prologue]
+ response_texts.extend(formatted_traceback)
+ response_texts.append(error_epilogue)
+ response_texts.append(html_epilogue)
+ response_body = bytes(os.linesep.join(response_texts), 'utf-8')
+
+ # HTTP response code and message
+ status = '200 OK'
+
+ # HTTP headers expected by the client
+ # They must be wrapped as a list of tupled pairs:
+ # [(Header name, Header value)].
+ response_headers = [
+ ('Content-Type', 'text/html'),
+ ('Content-Length', str(len(response_body)))
+ ]
+
+ # Send them to the server using the supplied function
+ start_response(status, response_headers)
+
+ # Return the response body. Notice it is wrapped
+ # in a list although it could be any iterable.
+ return [response_body]
+
+application = password_change_app
systemctl disable httpd.service
systemctl disable oddjobd.service
+systemctl disable pds.service
systemctl disable postfix.service
+systemctl disable rsyncd.service
systemctl disable sssd.service
systemctl disable NetworkManager-wait-online.service
--- /dev/null
+#!/bin/sh
+
+
+. $1
+
+
+/usr/bin/rsync \
+ --archive \
+ --delete-after \
+ --info=STATS \
+ --mkpath \
+ fdc.in.useribm.hu::pdsdb \
+ $CONTAINER_BUILDROOT/c3d/postinstall/install-data/var/lib/pds
SPEC_PACKAGES="authselect \
cronie \
httpd \
+ mkpasswd \
oddjob-mkhomedir \
openldap-clients \
openssh-clients \