def test_email(config, recipient, subject, body, sender=None, reply_to=None): """ Sends an email via the SMTP Database Object :param config: The email configuration :type config: SMTPServer Database Model :param recipient: The recipients of the email :type recipient: list :param subject: The subject of the email :type subject: basestring :param body: The body of the email :type body: basestring :param sender: An optional sender of the email. The SMTP database object has its own sender. This parameter can be used to override the internal sender. :type sender: basestring :param reply_to: The Reply-To parameter :type reply_to: basestring :return: True or False """ if type(recipient) != list: recipient = [recipient] mail_from = sender or config.sender reply_to = reply_to or mail_from msg = MIMEText(body.encode('utf-8'), 'plain', 'utf-8') msg['Subject'] = subject msg['From'] = mail_from msg['To'] = ",".join(recipient) msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) msg['Reply-To'] = reply_to mail = smtplib.SMTP(config.server, port=int(config.port), timeout=TIMEOUT) mail.ehlo() # Start TLS if required if config.tls: log.debug("Trying to STARTTLS: {0!s}".format(config.tls)) mail.starttls() # Authenticate, if a username is given. if config.username: log.debug("Doing authentication with {0!s}".format(config.username)) password = decryptPassword(config.password) if password == FAILED_TO_DECRYPT_PASSWORD: password = config.password mail.login(config.username, password) r = mail.sendmail(mail_from, recipient, msg.as_string()) log.info("Mail sent: {0!s}".format(r)) # r is a dictionary like {"*****@*****.**": (200, 'OK')} # we change this to True or False success = True for one_recipient in recipient: res_id, res_text = r.get(one_recipient, (200, "OK")) if res_id != 200 and res_text != "OK": success = False log.error("Failed to send email to {0!s}: {1!s}, {2!s}".format(one_recipient, res_id, res_text)) mail.quit() return success
def list_smtpservers(identifier=None, server=None): """ This returns a list of all smtpservers matching the criterion. If no identifier or server is provided, it will return a list of all smtp server definitions. :param identifier: The identifier or the name of the SMTPServer definition. As the identifier is unique, providing an identifier will return a list with either one or no smtpserver :type identifier: basestring :param server: The FQDN or IP address of the smtpserver :type server: basestring :return: list of SMTPServer configuration dicts. """ res = {} # get list of smtpserver objects server_obj_list = get_smtpservers(identifier=identifier, server=server) # transfer the definitions to a dictionary for server_obj in server_obj_list: decrypted_password = decryptPassword(server_obj.config.password) # If the database contains garbage, use the empty password as fallback if decrypted_password == FAILED_TO_DECRYPT_PASSWORD: decrypted_password = "" res[server_obj.config.identifier] = server_obj.config.get() res[server_obj.config.identifier].pop('id') res[server_obj.config.identifier].pop('identifier') res[server_obj.config.identifier].update({"password": decrypted_password}) return res
def test_01_encrypt_decrypt_pass(self): r = encryptPassword("passwörd") pin = decryptPassword(r) self.assertTrue(pin == "passwörd", (r, pin)) r = encryptPassword(u"passwörd") pin = decryptPassword(r, convert_unicode=True) self.assertEqual(pin, u"passwörd") r = encryptPassword(u"passwörd") pin = decryptPassword(r, convert_unicode=False) self.assertEqual(pin, "passwörd") # error path returns the bytestring r = encryptPassword(b"\x01\x02\x03\x04") self.assertEqual(decryptPassword(r, convert_unicode=True), b"\x01\x02\x03\x04")
def getResolverInfo(resolvername): ''' return the resolver info of the given resolvername :param resolvername: the requested resolver :type resolvername: string :return : dict of resolver description ''' resolver_dict = {} typ = "" resolvertypes = get_resolver_types() descr = {} conf = get_privacyIDEA_config() for entry in conf: for typ in resolvertypes: ## get the typed values of the descriptor! resolver_conf = get_resolver_classConfig(typ) if typ in resolver_conf: descr = resolver_conf.get(typ).get('config', {}) else: descr = resolver_conf if entry.startswith("privacyidea." + typ) and entry.endswith(resolvername): #the realm might contain dots "." # so take all after the 3rd dot for realm resolver = entry.split(".", 3) # An old entry without resolver name if len(resolver) <= 3: break value = conf.get(entry) if resolver[2] in descr: configEntry = resolver[2] if descr.get(configEntry) == 'password': ## do we already have the decrypted pass? if 'enc' + entry in conf: value = conf.get('enc' + entry) else: ## if no, we take the encpass and decrypt it value = conf.get(entry) try: en = decryptPassword(value) value = en except: log.info("Decryption of resolver passwd failed: compatibility issue?") resolver_dict[ resolver[2] ] = value # Dont check the other resolver types break return { "type" : typ, "data" : resolver_dict, "resolver" : resolvername}
def test_01_encrypt_decrypt_pass(self): r = encryptPassword(u"passwörd".encode('utf8')) # encryptPassword returns unicode self.assertTrue(isinstance(r, text_type)) pin = decryptPassword(r) # decryptPassword always returns unicode self.assertEqual(pin, u"passwörd") r = encryptPassword(u"passwörd") pin = decryptPassword(r) self.assertEqual(pin, u"passwörd") # decrypt some passwords generated with 2.23 pw1 = '3d1bf9db4c75469b4bb0bc7c70133181:2c27ac3839ed2213b8399d0471b17136' self.assertEqual(decryptPassword(pw1), 'test123') pw2 = '3a1be65a234f723fe5c6969b818582e1:08e51d1c65aa74c4988d094c40cb972c' self.assertEqual(decryptPassword(pw2), 'test123') pw3 = '7a4d5e2f26978394e33715bc3e8188a3:90b2782112ad7bbc5b48bd10e5c7c096cfe4ef7d9d11272595dc5b6c7f21d98a' self.assertEqual(decryptPassword(pw3, ), u'passwörd') # TODO: add checks for broken paddings/encrypted values and malformed enc_data not_valid_password = b"\x01\x02\x03\x04\xff" r = encryptPassword(not_valid_password) # A non valid password will raise an exception during decryption self.assertEqual(decryptPassword(r), 'FAILED TO DECRYPT PASSWORD!') # A value with missing colon (IV) will fail to decrypt self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
def test_01_encrypt_decrypt_pass(self): r = encryptPassword(u"passwörd".encode('utf8')) # encryptPassword returns unicode self.assertTrue(isinstance(r, text_type)) pin = decryptPassword(r) # decryptPassword always returns unicode self.assertEqual(pin, u"passwörd") r = encryptPassword(u"passwörd") pin = decryptPassword(r) self.assertEqual(pin, u"passwörd") not_valid_password = b"\x01\x02\x03\x04\xff" r = encryptPassword(not_valid_password) # A non valid password will raise an exception during decryption self.assertEqual(decryptPassword(r), 'FAILED TO DECRYPT PASSWORD!') # A value with missing colon (IV) will fail to decrypt self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
def test_01_encrypt_decrypt_pass(self): r = encryptPassword(u"passwörd".encode('utf8')) pin = decryptPassword(r) self.assertEqual(pin, u"passwörd".encode('utf8')) r = encryptPassword(u"passwörd") pin = decryptPassword(r, convert_unicode=True) self.assertEqual(pin, u"passwörd") r = encryptPassword(u"passwörd") pin = decryptPassword(r, convert_unicode=False) self.assertEqual(pin, u"passwörd".encode('utf8')) # error path returns the bytestring bs = b"\x01\x02\x03\x04\xff" r = encryptPassword(bs) self.assertEqual(decryptPassword(r, convert_unicode=True), bs) self.assertEqual(decryptPassword('test'), 'FAILED TO DECRYPT PASSWORD!')
def test_email(config, recipient, subject, body, sender=None): """ Sends an email via the SMTP Database Object :param config: The email configuration :type config: SMTPServer Database Model :param recipient: The recipients of the email :type recipient: list :param subject: The subject of the email :type subject: basestring :param body: The body of the email :type body: basestring :param sender: An optional sender of the email. The SMTP database object has its own sender. This parameter can be used to override the internal sender. :type sender: basestring :return: True or False """ if type(recipient) != list: recipient = [recipient] mail_from = sender or config.sender msg = MIMEText(body) msg['Subject'] = subject msg['From'] = mail_from msg['To'] = ",".join(recipient) msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) mail = smtplib.SMTP(config.server, port=int(config.port)) mail.ehlo() # Start TLS if required if config.tls: log.debug("Trying to STARTTLS: {0!s}".format(config.tls)) mail.starttls() # Authenticate, if a username is given. if config.username: log.debug("Doing authentication with {0!s}".format(config.username)) password = decryptPassword(config.password) if password == FAILED_TO_DECRYPT_PASSWORD: password = config.password mail.login(config.username, password) r = mail.sendmail(mail_from, recipient, msg.as_string()) log.info("Mail sent: {0!s}".format(r)) # r is a dictionary like {"*****@*****.**": (200, 'OK')} # we change this to True or False success = True for one_recipient in recipient: res_id, res_text = r.get(one_recipient, (200, "OK")) if res_id != 200 and res_text != "OK": success = False log.error("Failed to send email to {0!s}: {1!s}, {2!s}".format(one_recipient, res_id, res_text)) mail.quit() return success
def test_email(config, recipient, subject, body, sender=None): """ Sends an email via the SMTP Database Object :param config: The email configuration :type config: SMTPServer Database Model :param recipient: The recipients of the email :type recipient: list :param subject: The subject of the email :type subject: basestring :param body: The body of the email :type body: basestring :param sender: An optional sender of the email. The SMTP database object has its own sender. This parameter can be used to override the internal sender. :type sender: basestring :return: True or False """ mail_from = sender or config.sender date = datetime.datetime.utcnow().strftime("%c") body = """From: %s Subject: %s Date: %s %s""" % (mail_from, subject, date, body) mail = smtplib.SMTP(config.server, port=int(config.port)) mail.ehlo() # Start TLS if required if config.tls: log.debug("Trying to STARTTLS: %s" % config.tls) mail.starttls() # Authenticate, if a username is given. if config.username: log.debug("Doing authentication with %s" % config.username) password = decryptPassword(config.password) mail.login(config.username, password) r = mail.sendmail(mail_from, recipient, body) log.info("Mail sent: %s" % r) # r is a dictionary like {"*****@*****.**": (200, 'OK')} # we change this to True or False if type(recipient) != list: recipient = [recipient] success = True for one_recipient in recipient: res_id, res_text = r.get(one_recipient, (200, "OK")) if res_id != 200 and res_text != "OK": success = False log.error("Failed to send email to %s: %s, %s" % (recipient, res_id, res_text)) mail.quit() return success
def request(config, user, password): """ Perform a RADIUS request to a RADIUS server. The RADIUS configuration contains the IP address, the port and the secret of the RADIUS server. * config.server * config.port * config.secret :param config: The RADIUS configuration :type config: RADIUSServer Database Model :param user: the radius username :param password: the radius password :return: True or False. If any error occurs, an exception is raised. """ success = False nas_identifier = get_from_config("radius.nas_identifier", "privacyIDEA") r_dict = config.dictionary or get_from_config("radius.dictfile", "/etc/privacyidea/" "dictionary") log.debug("NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, r_dict)) log.debug("constructing client object " "with server: %r, port: %r, secret: %r" % (config.server, config.port, config.secret)) srv = Client(server=config.server, authport=config.port, secret=decryptPassword(config.secret), dict=Dictionary(r_dict)) req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name=user.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(password) response = srv.SendPacket(req) if response.code == pyrad.packet.AccessAccept: log.info("Radiusserver %s granted " "access to user %s." % (config.server, user)) success = True else: log.warning("Radiusserver %s" "rejected access to user %s." % (config.server, user)) return success
def request(config, user, password): """ Perform a RADIUS request to a RADIUS server. The RADIUS configuration contains the IP address, the port and the secret of the RADIUS server. * config.server * config.port * config.secret :param config: The RADIUS configuration :type config: RADIUSServer Database Model :param user: the radius username :param password: the radius password :return: True or False. If any error occurs, an exception is raised. """ success = False nas_identifier = get_from_config("radius.nas_identifier", "privacyIDEA") r_dict = config.dictionary or get_from_config( "radius.dictfile", "/etc/privacyidea/" "dictionary") log.debug("NAS Identifier: %r, " "Dictionary: %r" % (nas_identifier, r_dict)) log.debug("constructing client object " "with server: %r, port: %r, secret: %r" % (config.server, config.port, config.secret)) srv = Client(server=config.server, authport=config.port, secret=decryptPassword(config.secret), dict=Dictionary(r_dict)) req = srv.CreateAuthPacket( code=pyrad.packet.AccessRequest, User_Name=user.encode('ascii'), NAS_Identifier=nas_identifier.encode('ascii')) req["User-Password"] = req.PwCrypt(password) response = srv.SendPacket(req) if response.code == pyrad.packet.AccessAccept: log.info("Radiusserver %s granted " "access to user %s." % (config.server, user)) success = True else: log.warning("Radiusserver %s" "rejected access to user %s." % (config.server, user)) return success
def list_radiusservers(identifier=None, server=None): res = {} server_list = get_radiusservers(identifier=identifier, server=server) for server in server_list: decrypted_password = decryptPassword(server.config.secret) # If the database contains garbage, use the empty password as fallback if decrypted_password == FAILED_TO_DECRYPT_PASSWORD: decrypted_password = "" res[server.config.identifier] = { "server": server.config.server, "port": server.config.port, "dictionary": server.config.dictionary, "description": server.config.description, "password": decrypted_password, "timeout": server.config.timeout, "retries": server.config.retries } return res
def _retrieveAllConfigDB(): config = {} delay = False for conf in Session.query(Config).all(): log.debug("key %r:%r" % (conf.Key, conf.Value)) key = conf.Key if (not key.startswith("privacyidea.")): key = "privacyidea." + conf.Key nVal = _expandHere(conf.Value) config[key] = nVal myTyp = conf.Type if myTyp is not None: if myTyp == 'password': if hasattr(c, 'hsm') == True and isinstance(c.hsm, dict): hsm = c.hsm.get('obj') if hsm is not None and hsm.isReady() == True: config['enc' + key] = decryptPassword(conf.Value) else: delay = True return (config, delay)
def _storeConfigDB(key, val, typ=None, desc=None): value = val if (not key.startswith("privacyidea.")): key = "privacyidea." + key confEntries = Session.query(Config).filter(Config.Key == unicode(key)) theConf = None if typ is not None and typ == 'password': value = encryptPassword(val) en = decryptPassword(value) if (en != val): raise Exception("StoreConfig: Error during encoding password type!") ## update if confEntries.count() == 1: theConf = confEntries[0] theConf.Value = unicode(value) if (typ is not None): theConf.Type = unicode(typ) if (desc is not None): theConf.Description = unicode(desc) ## insert elif confEntries.count() == 0: theConf = Config( Key=unicode(key), Value=unicode(value), Type=unicode(typ), Description=unicode(desc) ) if theConf is not None: Session.add(theConf) return 101
def get_secret(self): return decryptPassword(self.config.secret)
def test_email(config, recipient, subject, body, sender=None, reply_to=None, mimetype="plain"): """ Sends an email via the configuration. :param config: The email configuration :type config: dict :param recipient: The recipients of the email :type recipient: list :param subject: The subject of the email :type subject: basestring :param body: The body of the email :type body: basestring :param sender: An optional sender of the email. The SMTP database object has its own sender. This parameter can be used to override the internal sender. :type sender: basestring :param reply_to: The Reply-To parameter :type reply_to: basestring :param mimetype: The type of the email to send. Can by plain or html :return: True or False """ if type(recipient) != list: recipient = [recipient] mail_from = sender or config['sender'] reply_to = reply_to or mail_from msg = MIMEText(body.encode('utf-8'), mimetype, 'utf-8') msg['Subject'] = subject msg['From'] = mail_from msg['To'] = ",".join(recipient) msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) msg['Reply-To'] = reply_to mail = smtplib.SMTP(config['server'], port=int(config['port']), timeout=config.get('timeout', TIMEOUT)) log.debug(u"submitting message to {0!s}".format(msg["To"])) log.debug("Saying EHLO to mailserver {0!s}".format(config['server'])) r = mail.ehlo() log.debug("mailserver responded with {0!s}".format(r)) # Start TLS if required if config.get('tls', False): log.debug("Trying to STARTTLS: {0!s}".format(config['tls'])) mail.starttls() # Authenticate, if a username is given. if config.get('username', ''): log.debug("Doing authentication with {0!s}".format( config['username'])) password = decryptPassword(config['password']) if password == FAILED_TO_DECRYPT_PASSWORD: password = config['password'] # Under Python 2, we pass passwords as bytestrings to get CRAM-MD5 to work. # We add a safeguard config option to disable the conversion. # Under Python 3, we pass passwords as unicode. if six.PY2 and get_app_config_value("PI_SMTP_PASSWORD_AS_BYTES", True): password = to_bytes(password) mail.login(config['username'], password) r = mail.sendmail(mail_from, recipient, msg.as_string()) log.info("Mail sent: {0!s}".format(r)) # r is a dictionary like {"*****@*****.**": (200, 'OK')} # we change this to True or False success = True for one_recipient in recipient: res_id, res_text = r.get(one_recipient, (200, "OK")) if res_id != 200 and res_text != "OK": success = False log.error("Failed to send email to {0!r}: {1!r}, {2!r}".format( one_recipient, res_id, res_text)) mail.quit() log.debug("I am done sending your email.") return success
def test_01_encrypt_decrypt_pass(self): r = encryptPassword("passwörd") pin = decryptPassword(r) self.assertTrue(pin == "passwörd", (r, pin))
def test_email(config, recipient, subject, body, sender=None, reply_to=None, mimetype="plain"): """ Sends an email via the configuration. :param config: The email configuration :type config: dict :param recipient: The recipients of the email :type recipient: list :param subject: The subject of the email :type subject: basestring :param body: The body of the email :type body: basestring :param sender: An optional sender of the email. The SMTP database object has its own sender. This parameter can be used to override the internal sender. :type sender: basestring :param reply_to: The Reply-To parameter :type reply_to: basestring :param mimetype: The type of the email to send. Can by plain or html :return: True or False """ if type(recipient) != list: recipient = [recipient] mail_from = sender or config['sender'] reply_to = reply_to or mail_from msg = MIMEText(body.encode('utf-8'), mimetype, 'utf-8') msg['Subject'] = subject msg['From'] = mail_from msg['To'] = ",".join(recipient) msg['Date'] = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) msg['Reply-To'] = reply_to mail = smtplib.SMTP(config['server'], port=int(config['port']), timeout=config.get('timeout', TIMEOUT)) log.debug(u"submitting message to {0!s}".format(msg["To"])) log.debug("Saying EHLO to mailserver {0!s}".format(config['server'])) r = mail.ehlo() log.debug("mailserver responded with {0!s}".format(r)) # Start TLS if required if config.get('tls', False): log.debug("Trying to STARTTLS: {0!s}".format(config['tls'])) mail.starttls() # Authenticate, if a username is given. if config.get('username', ''): log.debug("Doing authentication with {0!s}".format(config['username'])) password = decryptPassword(config['password']) if password == FAILED_TO_DECRYPT_PASSWORD: password = config['password'] # Under Python 2, we pass passwords as bytestrings to get CRAM-MD5 to work. # We add a safeguard config option to disable the conversion. # Under Python 3, we pass passwords as unicode. if six.PY2 and get_app_config_value("PI_SMTP_PASSWORD_AS_BYTES", True): password = to_bytes(password) mail.login(config['username'], password) r = mail.sendmail(mail_from, recipient, msg.as_string()) log.info("Mail sent: {0!s}".format(r)) # r is a dictionary like {"*****@*****.**": (200, 'OK')} # we change this to True or False success = True for one_recipient in recipient: res_id, res_text = r.get(one_recipient, (200, "OK")) if res_id != 200 and res_text != "OK": success = False log.error("Failed to send email to {0!r}: {1!r}, {2!r}".format(one_recipient, res_id, res_text)) mail.quit() log.debug("I am done sending your email.") return success