int SASLCleanXKMSPassPhrase()

in xsec/enc/XSECCryptoUtils.cpp [75:251]


int SASLCleanXKMSPassPhrase(unsigned char * input, int inputLen, safeBuffer &output) {

    // For now - this does *not* implement the full SASLPrep algorithm.
    // THe NFKC form is not trivial to implement - so this is kept very simple.
    // TODO - Fix this - it can be an interoperability issue as pass phrases from
    // different implementations could be treated differently.
    // Currently we only check for prohibited unput for chars < 0xFFFF and drop any
    // chars over 0xFFFF

    unsigned char * inp = new unsigned char[inputLen + 1];
    ArrayJanitor<unsigned char> j_inp(inp);
    memcpy(inp, input, inputLen);
    inp[inputLen] = '\0';

    XSECAutoPtrXMLCh uinput((char *) inp);
    XMLSize_t l = XMLString::stringLen(uinput.get());
    XMLCh* uoutput = new XMLCh[l + 1];
    ArrayJanitor<XMLCh> j_uoutput(uoutput);

    XMLSize_t i, j;
    j = 0;

    XMLCh ch1;

    for (i = 0; i < l; ++i) {

        ch1 = uinput.get()[i];
        // Case one - char is < 0x10000
        if (ch1 < 0xD800 || ch1 > 0xDFFF) {

            // OK - ch1 is "real" value - let's see if it is legal
            // The following switch tables are derived from
            // RFC 3454 - see http://www.ietf.org/rfc/rfc3454.txt

            // Non-ASCII Spaces - C.1.2
            switch (ch1) {

            case 0x00A0:        // NO-BREAK SPACE
            case 0x1680:        // OGHAM SPACE MARK
            case 0x2000:        // EN QUAD
            case 0x2001:        // EM QUAD
            case 0x2002:        // EN SPACE
            case 0x2003:        // EM SPACE
            case 0x2004:        // THREE-PER-EM SPACE
            case 0x2005:        // FOUR-PER-EM SPACE
            case 0x2006:        // SIX-PER-EM SPACE
            case 0x2007:        // FIGURE SPACE
            case 0x2008:        // PUNCTUATION SPACE
            case 0x2009:        // THIN SPACE
            case 0x200A:        // HAIR SPACE
            case 0x200B:        // ZERO WIDTH SPACE
            case 0x202F:        // NARROW NO-BREAK SPACE
            case 0x205F:        // MEDIUM MATHEMATICAL SPACE
            case 0x3000:        // IDEOGRAPHIC SPACE

                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - Non ASCII space character in XKMS pass phrase");
            default:

                break;

            }

            // ASCII Control characters
            // Note - us unsigned, so always >= 0)
            if ((ch1 <= 0x1F) || (ch1 == 0x7F)) {
                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - ASCII control character in XKMS pass phrase");
            }

            // Non-ASCII Control Characters
            if ((ch1 >= 0x80 && ch1 <= 0x9F) ||
                (ch1 >= 0x206A && ch1 <= 0x206F) ||
                (ch1 >= 0xFFF9 && ch1 <= 0xFFFC)) {

                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - NON ASCII control character in XKMS pass phrase");
            }

            switch (ch1) {


            case 0x06DD:        // ARABIC END OF AYAH
            case 0x070F:        // SYRIAC ABBREVIATION MARK
            case 0x180E:        // MONGOLIAN VOWEL SEPARATOR
            case 0x200C:        // ZERO WIDTH NON-JOINER
            case 0x200D:        // ZERO WIDTH JOINER
            case 0x2028:        // LINE SEPARATOR
            case 0x2029:        // PARAGRAPH SEPARATOR
            case 0x2060:        // WORD JOINER
            case 0x2061:        // FUNCTION APPLICATION
            case 0x2062:        // INVISIBLE TIMES
            case 0x2063:        // INVISIBLE SEPARATOR
            case 0xFEFF:        // ZERO WIDTH NO-BREAK SPACE
                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - NON ASCII control character in XKMS pass phrase");
            default:
                break;            }
            // 1D173-1D17A; [MUSICAL CONTROL CHARACTERS] is not relevant as we are looking at
            // ch1 at the moment

            // Private Use characters
            if ((ch1 >= 0xE000 && ch1 <= 0xF8FF)) {

                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - Private Use character in XKMS pass phrase");
            }

            // Non-character code points
            if ((ch1 >= 0xFDD0 && ch1 <= 0xFDEF) ||
                (ch1 >= 0xFFFE)) {

                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - Non-character code points in XKMS pass phrase");
            }

            // Inappropriate for plain text characters
   
            switch (ch1) {
            case 0xFFF9:        // INTERLINEAR ANNOTATION ANCHOR
            case 0xFFFA:        // INTERLINEAR ANNOTATION SEPARATOR
            case 0xFFFB:        // INTERLINEAR ANNOTATION TERMINATOR
            case 0xFFFC:        // OBJECT REPLACEMENT CHARACTER
            case 0xFFFD:        // REPLACEMENT CHARACTER
                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - Innappropriate for plain text chararcters in XKMS pass phrase");
            default:
                break;
            }

            // Inappripriate for canonical representation characters
            if (ch1 >= 0x2FF0 && ch1 <= 0x2FFB) {
                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - Innappropriate for canonicalisation chararcters in XKMS pass phrase");
            }

            // Change display properties or are deprecated
            switch (ch1) {
            case 0x0340:        // COMBINING GRAVE TONE MARK
            case 0x0341:        // COMBINING ACUTE TONE MARK
            case 0x200E:        // LEFT-TO-RIGHT MARK
            case 0x200F:        // RIGHT-TO-LEFT MARK
            case 0x202A:        // LEFT-TO-RIGHT EMBEDDING
            case 0x202B:        // RIGHT-TO-LEFT EMBEDDING
            case 0x202C:        // POP DIRECTIONAL FORMATTING
            case 0x202D:        // LEFT-TO-RIGHT OVERRIDE
            case 0x202E:        // RIGHT-TO-LEFT OVERRIDE
            case 0x206A:        // INHIBIT SYMMETRIC SWAPPING
            case 0x206B:        // ACTIVATE SYMMETRIC SWAPPING
            case 0x206C:        // INHIBIT ARABIC FORM SHAPING
            case 0x206D:        // ACTIVATE ARABIC FORM SHAPING
            case 0x206E:        // NATIONAL DIGIT SHAPES
            case 0x206F:        // NOMINAL DIGIT SHAPES
                throw XSECException(XSECException::XKMSError,
                    "SASLCleanXKMSPassPhrase - change display or deprecated chararcters in XKMS pass phrase");
            default:
                break;
            }

            // We got this far = just run with it for now
            uoutput[j++] = ch1;
        }
        else {
            throw XSECException(XSECException::XKMSError,
                "SASLCleanXKMSPassPhrase - don't support XKMS pass phrase chars > 0xFFFF");
        }
    } /* for */
    uoutput[j++] = chNull;

    // Now transcode
    char * utf8output= transcodeToUTF8(uoutput);
    output.sbStrcpyIn(utf8output);

    int ret = (int)strlen(utf8output);
    XSEC_RELEASE_XMLCH(utf8output);
    return ret;
}