1. Home
  2. Encrypt Emails in SAP
Encrypt Emails in SAP

General Information

So what we basically want to do - we encrypt the email with the user public ceritifcate (the user is the our TO-Recipient of the email)

to encrypt emails we would need to override those interface methods:

  • IF_BADI_SMIME_EMAIL~CERTIFICATE_RETRIEVAL
  • IF_BADI_SMIME_EMAIL~CERTIFICATE_SELECTION

Note, that this methods are called after emails where pickuped from the mail queue

Implementation

If we get the user certificate, we store this in it_certificates and then select it for the encrpytion.
So our Method IF_BADI_SMIME_EMAIL~CERTIFICATE_SELECTION.

would be like this:

  method IF_BADI_SMIME_EMAIL~CERTIFICATE_SELECTION.
    DATA:
      lt_certificates TYPE if_badi_smime_email=>tt_certificates_x509.

    lt_certificates = it_certificates.

    " Filter out unsuitable certificates by some default criteria
    CALL METHOD default_filter
      CHANGING
        ct_certificates = lt_certificates.

    " When only one certificate is left, it is used, otherwise error
    CASE lines( lt_certificates ).
      WHEN 0.
        RAISE EXCEPTION TYPE cx_smime_crypto
          EXPORTING
            textid   = cx_smime_crypto=>certificate_not_found
            email    = if_email.
      WHEN 1.
        READ TABLE lt_certificates INTO ro_certificate INDEX 1.
      WHEN OTHERS.
        RAISE EXCEPTION TYPE cx_smime_crypto
          EXPORTING
            textid   = cx_smime_crypto=>certificate_ambiguous
            email    = if_email.
    ENDCASE.
  endmethod.

now let's see how we can retrieve the certificate

Method 1 - get certificate from the STRUST Adress Book

  method IF_BADI_SMIME_EMAIL~CERTIFICATE_RETRIEVAL.

*  enhanced method to retrieve certificates form Address-book or LDAP server.
*
*  PARAMETERS:
*     IF_MAIL - email address of the receiver. For that email a public certificate should be retrieved, to
*               encrypt email body.
*

    DATA:
      l_strustemail    TYPE strustemail, " trust mail for address book, tmp variable
      lt_strustcertificates TYPE strustcerttab, " list of certificates


    CLEAR et_certificates.

*   ===
*   Find user in address book.
*

    " Format change for Email (STRING --> CHAR254)
    l_strustemail = IF_EMAIL.
    IF l_strustemail <> if_email.
      RAISE EXCEPTION TYPE cx_smime_crypto
        EXPORTING
          textid   = cx_smime_crypto=>email_address_too_long
          email    = if_email.
    ENDIF.

    " Lookup in address book (no structural checks by this method)
    CALL FUNCTION 'STRUSTCAB_GET_CERTS_BY_EMAIL'
      EXPORTING
        if_email        = l_strustemail
      IMPORTING
        et_certificates = lt_strustcertificates
      EXCEPTIONS
        not_found       = 1
        invalid_email   = 2
        OTHERS          = 3.
    CASE sy-subrc.
      WHEN 0.
        " FOUND -> RETURN
        et_certificates = lt_strustcertificates.
        RETURN.
        " The exception "NOT_FOUND" results in an empty list, which later
        " leads to a "no certificate found" in CERTIFICATE_SELECTION.
        " Don't need that code duplicate.
      WHEN OTHERS.
        " Not found
        " would proceed with LDAP
    ENDCASE.
endmethod    

Method 2 - get certificate from LDAP, Active Directory

if we use LDAP / ActiveDirectory we can basically store user certificates there and then we can get them. Let's assume the user certificate (we would find user by Email) is stored in LDAP in the parameter USERCERTIFICATE

we extend our method for certificate retrieval with following procedures:

first let's bind to LDAP Server

CALL FUNCTION 'LDAP_SYSTEMBIND'
      EXPORTING
        serverid     = gc_ldap_id
        wait_time    = gc_wait_time
      EXCEPTIONS
        no_authoriz  = 1
        config_error = 2
        nomore_conns = 3
        ldap_failure = 4
        not_alive    = 5
        other_error  = 6
        OTHERS       = 7.
    IF sy-subrc NE 0.
      RAISE EXCEPTION TYPE cx_smime_crypto
      EXPORTING
        textid   = cx_smime_crypto=>FREETEXT_MESSAGE
        krn_msg  = 'LDAP BIND error '
        email    = if_email.
    ENDIF.

Read user data from LDAP

" generate search. IF_MAIL - incoming variable.
    CONCATENATE '(&(mail=' IF_EMAIL '))' INTO l_ldap_search.

    " perform ldapsearch
    CALL FUNCTION 'LDAP_READ'
      EXPORTING
        scope               = 2
        filter              = l_ldap_search
      IMPORTING
        ldaprc              = l_ldaprc
        entries             = l_entries
      EXCEPTIONS
        no_authoriz         = 1
        conn_outdate        = 2
        ldap_failure        = 3
        not_alive           = 4
        other_error         = 5
        others              = 6.
    if sy-subrc =  0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*             WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    endif.

unbind LDAP Server

CALL FUNCTION 'LDAP_UNBIND'
        EXCEPTIONS
          conn_outdate = 0
          ldap_failure = 0
          not_alive    = 0
          other_error  = 0
          OTHERS       = 0.
    IF sy-subrc NE 0.
*        RAISE system_bind_error.
    ENDIF.

retrieve certificate form l_entries

IF l_entries[] IS INITIAL.
      concatenate 'EMPTY LDAP RESPONSE for email: ' if_email INTO error_msg.
      RAISE EXCEPTION TYPE cx_smime_crypto
            EXPORTING
              textid   = cx_smime_crypto=>FREETEXT_MESSAGE
              krn_msg  = error_msg
              email    = if_email.
    endif.

    read table l_entries into l_wa_entires index 1.

    l_attributes = l_wa_entires-ATTRIBUTES.
    read table l_attributes into l_wa_user_cert WITH TABLE KEY name = 'USERCERTIFICATE'.

    l_tblx_user_cert = l_wa_user_cert-XVALS.
    read table l_tblx_user_cert into l_linex_user_cert INDEX 1.
    l_x_user_cert = l_linex_user_cert-VAL.

    INSERT l_x_user_cert INTO TABLE et_certificates.

And that's it! Now we can encrypt our messages with user public certificates direct in SAP.