Example #1
0
    def _submitMessage(self, phone, message):
        """
        write the message down to the given file

        :param phone: given phone number
        :param message: the provided message, containing the otp
        """
        ret = False

        filename = self.config.get("file", "")
        here = self.config.get("here", "")

        if here:
            filename = "%s%s%s" % (here, os.path.sep, filename)
        try:
            with open(filename, "w") as f:
                msg = "%s:%s" % (str2unicode(phone), str2unicode(message))
                f.write(msg)
            ret = True

        except Exception as exx:
            log.error("Failed to open file %r", filename)
            raise ProviderNotAvailable("Failed to open file %r" % filename)

        return ret
Example #2
0
    def _submitMessage(self, phone, message):
        '''
        send out a message to a phone via an http sms connector
        :param phone: the phone number
        :param message: the message to submit to the phone
        '''

        log.debug("[submitMessage] submitting message "
                  "%s to %s" % (message, phone))

        pparams = {}

        # ----------------------------------------------------------------- --

        # care for the authentication

        if self.auth_type == 'basic':
            auth_method = HTTPBasicAuth

        elif self.auth_type == 'digest':
            auth_method = HTTPDigestAuth

        else:
            auth_method = None

        if self.username and auth_method:
            pparams['auth'] = auth_method(username=self.username,
                                          password=self.password)

        # ----------------------------------------------------------------- --

        # fill in the data into the payload

        json_body = {}
        json_body.update(self.payload)

        sms_message = json_body[self.sms_text_key]
        if sms_message and '<message>' in sms_message:
            sms_message = sms_message.replace('<message>', message)
        else:
            sms_message = message
        json_body[self.sms_text_key] = sms_message

        # ----------------------------------------------------------------- --

        # care for the phone number
        # do some phone number normalisation if MSISDN parameter is provided

        # prepare the phone number
        msisdn = 'true' in ("%r" % self.config.get('MSISDN', "false")).lower()
        if msisdn:
            phone = self._get_msisdn_phonenumber(phone)

        # ------------------------------------------------------------------ --

        # replace the phone if there is a given template for it

        sms_phone = self._apply_phone_template(
            phone, json_body.get(self.sms_phone_key))

        json_body[self.sms_phone_key] = sms_phone

        # ----------------------------------------------------------------- --

        # care for connection timeout

        if self.timeout:
            pparams['timeout'] = self.timeout

        # -------------------------------------------------------------- --

        # setup http headers

        # submitting the json body requires the correct HTTP headers
        # with contenttype declaration:

        headers = {
            'Content-type': 'application/json',
            'Accept': 'application/json'
        }

        if self.headers:
            headers.update(self.headers)

        http_session = requests.Session()

        # -------------------------------------------------------------- --

        # support for proxies

        if self.proxy:
            http_session.proxies.update(self.proxy)

        # ------------------------------------------------------------- --

        # client certificate -
        # we check if the client certificate exists, which is
        # referenced as a filename

        if self.client_cert and os.path.isfile(self.client_cert):
            http_session.cert = self.client_cert

        # ------------------------------------------------------------- --

        # server certificate

        server_cert = self.server_cert
        if server_cert is not None:
            # Session.post() doesn't like unicode values in Session.verify
            if isinstance(server_cert, str):
                server_cert = server_cert.encode('utf-8')

            http_session.verify = server_cert

        # ------------------------------------------------------------- --

        retry = 3

        while retry > 0:
            try:
                log.debug("Request Header: %r", headers)
                log.debug("Request Content: %r", json_body)
                response = http_session.post(self.urls[0],
                                             json=json_body,
                                             headers=headers,
                                             **pparams)

                if response.ok:
                    log.info("RestSMSProvider request success!")
                    log.debug("Response Headers: %r", response.headers)
                    log.debug("Response Content: %r", response.content)
                    return True

                log.info("RestSMSProvider request failed: %r", response.reason)
                return False

            except requests.exceptions.Timeout as exc:
                log.exception("RestSMSProvider timed out %r" % exc)
                retry -= 1
                if retry <= 0:
                    raise ProviderNotAvailable("RestSMSProvider timed out %r" %
                                               exc)

            except Exception as exc:
                log.exception("RestSMSProvider %r" % exc)
                retry = 0
                raise Exception("Failed to send SMS. %s" % str(exc))
Example #3
0
    def _submitMessage(self, phone, message):
        """
        submit the message to the SMPP Server
        """

        result = True

        # setup the configuration
        if not self.config:
            raise Exception("missing configuration!")

        try:
            client = smpplib.client.Client(self.server, self.port)
            client.connect()
            log.debug("connected to %r:%r", self.server, self.port)

        except Exception as exx:
            log.exception("Failed to connect to server")
            raise ProviderNotAvailable("Failed to connect to server %r" % exc)

        try:
            log.debug("binding to system_id %r (system_type %r)",
                      self.system_id, self.system_type)

            # transform the arguments from unicode down to string / byte array
            password = self.password.encode(self.target_encoding, 'ignore')
            system_id = self.system_id.encode(self.target_encoding, 'ignore')
            system_type = self.system_type.encode(self.target_encoding,
                                                  'ignore')

            client.bind_transceiver(system_id=system_id,
                                    password=password,
                                    system_type=system_type)

            # transform the arguments from unicode down to string / byte array
            source_addr = self.source_addr.encode(self.target_encoding,
                                                  'ignore')
            destination_addr = phone.encode(self.target_encoding, 'ignore')
            short_message = message.encode(self.target_encoding, 'ignore')

            # according to spec messages should not be longer than 160 chars
            if len(short_message) <= 160:
                self._send(client, source_addr, destination_addr,
                           short_message)
                log.debug("message %r submitted to %r", short_message, phone)

            else:
                # messages longer than 160 chars should be
                # split down into small chunks of 153 chars
                max_msg_len = 153
                for i in range(0, len(short_message), max_msg_len):
                    msg = short_message[i:i + max_msg_len]
                    if not msg:
                        continue
                    self._send(client, source_addr, destination_addr, msg)
                    log.debug("message %r submitted to %r", msg, phone)

        except Exception as exx:
            log.exception(exx)
            result = False

        finally:
            client.unbind()
            client.disconnect()

        return result
    def _submitMessage(self, phone, message):
        '''
        Submits the message for phone to the email gateway.

        Returns true in case of success
        '''
        ret = False
        if ('mailserver' not in self.config or
                'mailsender' not in self.config or 'mailto' not in self.config):
            log.error("[submitMessage] incomplete config: %s. mailserver, "
                      "mailsender and mailto needed." % self.config)
            return ret

        # prepare the phone number
        msisdn = 'true' in ("%r" % self.config.get('MSISDN', "false")).lower()
        if msisdn:
            phone = self._get_msisdn_phonenumber(phone)

        # prepare the smtp server connection parameters
        default_port = 25

        start_tls_params = {}
        start_tls = str(self.config.get("start_tls", False)).lower() == 'true'
        if start_tls:
            default_port = 587
            start_tls_params_keyfile = self.config.get("keyfile", None)
            start_tls_params_certfile = self.config.get("certfile", None)

        use_ssl = str(self.config.get("use_ssl", False)).lower() == 'true'
        if use_ssl:
            default_port = 465

        server = self.config.get("mailserver")
        port = int(self.config.get("mailserver_port", default_port))

        # support for mailserver syntax like server:port
        # if port is not explicit defined
        if "mailserver_port" not in self.config and ':' in server:
            server, _sep, port = server.rpartition(':')

        user = self.config.get("mailuser")
        password = self.config.get("mailpassword")

        fromaddr = self.config.get("mailsender", "linotp@localhost")
        toaddr = self.config.get("mailto")
        subject = self.config.get("subject", "")
        body = self.config.get("body", "")

        log.debug("[submitMessage] submitting message %s to %s",
                  message, phone)

        toaddr = string.replace(toaddr, PHONE_TAG, phone)

        if not subject:
            subject = "[LinOTP]"
        subject = string.replace(subject, PHONE_TAG, phone)
        subject = string.replace(subject, MSG_TAG, message)

        if not body:
            body = "<otp>"
        body = string.replace(body, PHONE_TAG, phone)
        body = string.replace(body, MSG_TAG, message)

        msg = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s"
               % (fromaddr, toaddr, subject, body))

        serv = None
        try:
            # if SSL is defined, we require a different base class
            if not use_ssl:
                serv = smtplib.SMTP(server, port)
            else:
                serv = smtplib.SMTP_SSL(server, port)
            serv.set_debuglevel(1)

            serv.ehlo()
            if start_tls and not use_ssl:
                if serv.has_extn('STARTTLS'):
                    serv.starttls(start_tls_params_keyfile,
                                  start_tls_params_certfile)
                    serv.ehlo()
                else:
                    log.error("Start_TLS not supported:")
                    raise Exception("Start_TLS requested but not supported"
                                    " by server %r" % server)
            if user:
                if serv.has_extn('AUTH'):
                    log.debug("authenticating to mailserver, user: %s, "
                              "pass: %r", user, sha256(password).hexdigest())
                    serv.login(user, password)
                else:
                    log.error("AUTH not supported:")

            data_dict = serv.sendmail(fromaddr, toaddr, msg)
            log.debug("sendmail: %r", data_dict)

            (code, response) = serv.quit()
            log.debug("quit: (%r) %r", code, response)
            ret = True

        except smtplib.socket.error as exc:
            log.exception('Error: could not connect to server')
            if boolean(self.config.get('raise_exception', True)):
                raise ProviderNotAvailable('Error: could not connect '
                                           'to server: %r' % exc)
            ret = False

        except Exception as exx:
            log.exception("[submitMessage] %s", exx)
            if boolean(self.config.get('raise_exception', False)):
                raise Exception(exx)
            ret = False

        finally:
            if serv:
                serv.close()

        return ret
Example #5
0
    def request(self,
                url,
                parameter,
                username=None,
                password=None,
                method='GET'):

        try:
            pparams = {}

            if 'timeout' in self.config and self.config['timeout']:
                pparams['timeout'] = parse_timeout(self.config['timeout'])

            if 'PROXY' in self.config and self.config['PROXY']:

                if isinstance(self.config['PROXY'], str):
                    proxy_defintion = {
                        "http": self.config['PROXY'],
                        "https": self.config['PROXY']
                    }

                elif isinstance(self.config['PROXY'], dict):
                    proxy_defintion = self.config['PROXY']

                pparams['proxies'] = proxy_defintion

            if username and password is not None:
                auth = None
                auth_type = self.config.get('AUTH_TYPE',
                                            'basic').lower().strip()

                if auth_type == 'basic':
                    auth = HTTPBasicAuth(username, password)

                if auth_type == 'digest':
                    auth = HTTPDigestAuth(username, password)

                if auth:
                    pparams['auth'] = auth

            # -------------------------------------------------------------- --

            # fianly execute the request

            if method == 'GET':
                response = requests.get(url, params=parameter, **pparams)
            else:
                response = requests.post(url, data=parameter, **pparams)

            reply = response.text
            # some providers like clickatell have no response.status!
            log.debug("HttpSMSProvider >>%r...%r<<", reply[:20], reply[-20:])
            ret = self._check_success(reply)

        except (requests.exceptions.ConnectTimeout,
                requests.exceptions.ConnectionError,
                requests.exceptions.Timeout, requests.exceptions.ReadTimeout,
                requests.exceptions.TooManyRedirects) as exc:

            log.exception("HttpSMSProvider timed out")
            raise ProviderNotAvailable("Failed to send SMS - timed out %r" %
                                       exc)

        except Exception as exc:
            log.error("HttpSMSProvider %r", exc)
            raise Exception("Failed to send SMS. %r" % exc)

        return ret
Example #6
0
    def request(self,
                url,
                parameter,
                username=None,
                password=None,
                method="GET"):

        try:
            pparams = {}

            pparams["timeout"] = HttpSMSProvider.DEFAULT_TIMEOUT
            if "timeout" in self.config and self.config["timeout"]:
                pparams["timeout"] = parse_timeout(self.config["timeout"])

            if "PROXY" in self.config and self.config["PROXY"]:

                if isinstance(self.config["PROXY"], str):
                    proxy_defintion = {
                        "http": self.config["PROXY"],
                        "https": self.config["PROXY"],
                    }

                elif isinstance(self.config["PROXY"], dict):
                    proxy_defintion = self.config["PROXY"]

                pparams["proxies"] = proxy_defintion

            if username and password is not None:
                auth = None
                auth_type = (self.config.get("AUTH_TYPE",
                                             "basic").lower().strip())

                if auth_type == "basic":
                    auth = HTTPBasicAuth(username, password)

                if auth_type == "digest":
                    auth = HTTPDigestAuth(username, password)

                if auth:
                    pparams["auth"] = auth

            # --------------------------------------------------------------

            # set server certificate validation policy

            server_certificate = self.load_server_cert(
                self.config, server_cert_key="SERVER_CERTIFICATE")

            if server_certificate is False:
                pparams["verify"] = False

            if server_certificate:
                pparams["verify"] = server_certificate

            # -------------------------------------------------------------- --

            # finally execute the request

            if method == "GET":
                response = requests.get(url, params=parameter, **pparams)
            else:
                response = requests.post(url, data=parameter, **pparams)

            reply = response.text
            # some providers like clickatell have no response.status!
            log.debug("HttpSMSProvider >>%r...%r<<", reply[:20], reply[-20:])
            ret = self._check_success(reply)

        except (
                requests.exceptions.ConnectTimeout,
                requests.exceptions.ConnectionError,
                requests.exceptions.Timeout,
                requests.exceptions.ReadTimeout,
                requests.exceptions.TooManyRedirects,
        ) as exc:

            log.error("HttpSMSProvider timed out")
            raise ProviderNotAvailable("Failed to send SMS - timed out %r" %
                                       exc)

        except Exception as exc:
            log.error("HttpSMSProvider %r", exc)
            raise Exception("Failed to send SMS. %r" % exc)

        return ret
Example #7
0
    def _submitMessage(self, phone, message):
        """
        send out a message to a phone via an http sms connector
        :param phone: the phone number
        :param message: the message to submit to the phone
        """

        log.debug("[submitMessage] submitting message %s to %s", message,
                  phone)

        pparams = {}

        # ----------------------------------------------------------------- --

        # care for the authentication

        if self.auth_type == "basic":
            auth_method = HTTPBasicAuth

        elif self.auth_type == "digest":
            auth_method = HTTPDigestAuth

        else:
            auth_method = None

        if self.username and auth_method:
            pparams["auth"] = auth_method(username=self.username,
                                          password=self.password)

        # ----------------------------------------------------------------- --

        # fill in the data into the payload

        json_body = deepcopy(self.payload)

        sms_message = json_body.get(self.sms_text_key, "")
        if sms_message and "<message>" in sms_message:
            sms_message = sms_message.replace("<message>", message)
        else:
            sms_message = message

        json_replace(json_body, key=self.sms_text_key, value=sms_message)

        # ----------------------------------------------------------------- --

        # care for the phone number
        # do some phone number normalisation if MSISDN parameter is provided

        # prepare the phone number
        msisdn = "true" in ("%r" % self.config.get("MSISDN", "false")).lower()
        if msisdn:
            phone = self._get_msisdn_phonenumber(phone)

        # ------------------------------------------------------------------ --

        # replace the phone if there is a given template for it

        sms_phone = self._apply_phone_template(
            phone, json_body.get(self.sms_phone_key))

        json_replace(json_body, key=self.sms_phone_key, value=sms_phone)

        # ----------------------------------------------------------------- --

        # care for connection timeout

        pparams["timeout"] = self.timeout

        # -------------------------------------------------------------- --

        # setup http headers

        # submitting the json body requires the correct HTTP headers
        # with contenttype declaration:

        headers = {
            "Content-type": "application/json",
            "Accept": "application/json",
        }

        if self.headers:
            headers.update(self.headers)

        http_session = requests.Session()

        # -------------------------------------------------------------- --

        # support for proxies

        if self.proxy:
            http_session.proxies.update(self.proxy)

        # ------------------------------------------------------------- --

        # client certificate -
        # we check if the client certificate exists, which is
        # referenced as a filename

        if self.client_cert and os.path.isfile(self.client_cert):
            http_session.cert = self.client_cert

        # ------------------------------------------------------------- --

        # set server certificate validation policy

        if self.server_cert is False:
            http_session.verify = False

        if self.server_cert:
            http_session.verify = self.server_cert

        # ------------------------------------------------------------- --

        retry = 3

        while retry > 0:
            try:
                log.debug("Request Header: %r", headers)
                log.debug("Request Content: %r", json_body)
                response = http_session.post(self.urls[0],
                                             json=json_body,
                                             headers=headers,
                                             **pparams)

                if response.ok:
                    log.info("RestSMSProvider request success!")
                    log.debug("Response Headers: %r", response.headers)
                    log.debug("Response Content: %r", response.content)
                    return True

                log.info("RestSMSProvider request failed: %r", response.reason)
                return False

            except requests.exceptions.Timeout as exc:
                log.error("RestSMSProvider timed out %r", exc)
                retry -= 1
                if retry <= 0:
                    raise ProviderNotAvailable("RestSMSProvider timed out %r" %
                                               exc)

            except Exception as exc:
                log.error("RestSMSProvider %r", exc)
                retry = 0
                raise Exception("Failed to send SMS. %s" % str(exc))