From: <svn...@op...> - 2009-02-19 17:26:28
|
Author: bellmich Date: Thu Feb 19 18:27:02 2009 New Revision: 935 URL: http://libsyncml.opensync.org/changeset/935 Log: massive update for OMA DS 1.2 SAN - removed trailing NULL bytes from all identifiers - added several new content types - added support for unknown content types like specified by OMA (set content type number to 0x00 0x00 0x00 and use only the identifier to determine the data store) - added implementation for correct digest generation including support for authentication without nonce (BTW I do not know a phone which actually checks the digest) Modified: trunk/libsyncml/sml_notification.c Modified: trunk/libsyncml/sml_notification.c ============================================================================== --- trunk/libsyncml/sml_notification.c Thu Feb 19 18:20:05 2009 (r934) +++ trunk/libsyncml/sml_notification.c Thu Feb 19 18:27:02 2009 (r935) @@ -27,6 +27,8 @@ #include "sml_command_internals.h" #include "sml_manager_internals.h" #include "sml_error_internals.h" +#include "objects/sml_auth_internals.h" +#include "sml_elements_internals.h" SmlNotification *smlNotificationNew(SmlNotificationVersion version, SmlNotificationUIMode mode, SmlNotificationInitiator init, unsigned int sessionID, const char *identifier, const char *target, SmlMimeType type, SmlError **error) { @@ -199,7 +201,8 @@ /* server identifier */ if (idLength) { - san->identifier = smlTryMalloc0(idLength, error); + /* the trailing NULL byte is usually not present in the SAN */ + san->identifier = smlTryMalloc0(idLength + 1, error); if (!san->identifier) goto error_free_san; @@ -238,6 +241,13 @@ /* The contenttype */ const char *alert_ct; switch (contenttype) { + case 0x00: + /* This is exactly like defined in "DS Protocol" section + * 12.4.13 "Content Type" of the official OMA document + * OMA-TS-DS_Protocol-V1_2_1-20070810-A.pdf. + */ + alert_ct = NULL; + break; case 0x07: alert_ct = SML_ELEMENT_TEXT_VCARD; break; @@ -247,6 +257,21 @@ case 0x03: alert_ct = SML_ELEMENT_TEXT_PLAIN; break; + case 0x0305: + alert_ct = SML_ELEMENT_TEXT_ICAL; + break; + case 0x0306: + alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_EMAIL; + break; + case 0x0307: + alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FILE; + break; + case 0x0308: + alert_ct = SML_ELEMENT_APPLICATION_OMA_DS_FOLDER; + break; + case 0x0309: + alert_ct = SML_ELEMENT_TEXT_VCARD_30; + break; default: /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */ smlErrorSet(error, SML_ERROR_GENERIC, "The OMNA WSP Content Type Number 0x%xd is not supported.", contenttype); @@ -256,6 +281,7 @@ /* The server uri */ char *alert_uri; if (idLength) { + /* the trailing NULL byte is usually not present in the SAN */ alert_uri = smlTryMalloc0(idLength + 1, error); if (!alert_uri) goto error_free_san; @@ -407,11 +433,11 @@ SmlSanAlert *alert = NULL; /* Calculate the length of the san data */ - unsigned int length = 16 /* Digest */ + 8 /* Hdr */ + strlen(san->identifier) + 1 /* Identifier */ + 1 /* num-sync + future */; + unsigned int length = 16 /* Digest */ + 8 /* Hdr */ + strlen(san->identifier) /* Identifier */ + 1 /* num-sync + future */; GList *a = NULL; for (a = san->alerts; a; a = a->next) { alert = a->data; - length += 5 + strlen(alert->serverURI) + 1; + length += 5 + strlen(alert->serverURI); numsync++; } @@ -421,11 +447,11 @@ goto error; *data = buffer; *size = length; - - /* FIXME: Now create the digest */ + + /* the digest must be created at the end */ /* Create Header */ - /* Version */ + /* Version - 10 bit */ buffer[16] = 0x03; /* ui mode */ @@ -434,17 +460,17 @@ /* initiator */ buffer[17] = buffer[17] | (san->init << 3); - /* future use is 0 for now */ + /* future use is 0 for now - 27 bit */ /* session id */ buffer[21] = san->sessionID >> 8; buffer[22] = san->sessionID; - /* server identifier */ - buffer[23] = strlen(san->identifier) + 1; - strcpy(buffer + 24, san->identifier); + /* server identifier without trailing NULL byte */ + buffer[23] = strlen(san->identifier); + strncpy(buffer + 24, san->identifier, strlen(san->identifier)); - buffer += 24 + strlen(san->identifier) + 1; + buffer += 24 + strlen(san->identifier); /* Num syncs + future */ buffer[0] = numsync << 4; @@ -456,23 +482,80 @@ buffer[0] = (alert->type - 200) << 4; /* The contenttype */ - if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD)) + if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD)) { buffer[3] = 0x07; - else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCAL)) + } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCAL)) { buffer[3] = 0x06; - else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_PLAIN)) + } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_PLAIN)) { buffer[3] = 0x03; - else { + } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_ICAL)) { + buffer[2] = 0x03; + buffer[3] = 0x05; + } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_EMAIL)) { + buffer[2] = 0x03; + buffer[3] = 0x06; + } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FILE)) { + buffer[2] = 0x03; + buffer[3] = 0x07; + } else if (!strcmp(alert->contenttype, SML_ELEMENT_APPLICATION_OMA_DS_FOLDER)) { + buffer[2] = 0x03; + buffer[3] = 0x08; + } else if (!strcmp(alert->contenttype, SML_ELEMENT_TEXT_VCARD_30)) { + buffer[2] = 0x03; + buffer[3] = 0x09; + } else { /* http://www.openmobilealliance.org/Tech/omna/omna-wsp-content-type.aspx */ - smlErrorSet(error, SML_ERROR_GENERIC, "The OMNA WSP Content Type Number is unknown for %s.", alert->contenttype); - goto error_free_data; + smlTrace(TRACE_INTERNAL, + "%s: The OMNA WSP Content Type Number is unknown for %s.", + __func__, alert->contenttype); + /* All bytes are already set to zero. */ } - /* The server uri */ - buffer[4] = strlen(alert->serverURI) + 1; - strcpy(buffer + 5, alert->serverURI); - buffer += 5 + strlen(alert->serverURI) + 1; + /* The server uri without a trailing NULL byte */ + buffer[4] = strlen(alert->serverURI); + strncpy(buffer + 5, alert->serverURI, strlen(alert->serverURI)); + buffer += 5 + strlen(alert->serverURI); + } + + /* Create the digest */ + + /* DO NOT USE buffer because this pointer was manipulated + * ALWAYS USE *data. + */ + + /* base64 encoded MD5 digest of the notification */ + unsigned char digest[16]; + smlMD5GetDigest (*data+16, length - 16 /* digest */, digest); + char *b64_san = g_base64_encode(digest, 16); + smlTrace(TRACE_INTERNAL, "%s: b64(md5(san)) ::= %s", __func__, b64_san); + + /* base64 encoded MD5 digest of username:password */ + const char *username = ""; + const char *password = ""; + if (san->cred) { + username = san->cred->username; + password = san->cred->password; } + char *auth = g_strdup_printf("%s:%s", username, password); + smlMD5GetDigest (auth, strlen(auth), digest); + smlSafeCFree(&auth); + char *b64_auth = g_base64_encode(digest, 16); + smlTrace(TRACE_INTERNAL, "%s: b64(md5(username:password)) ::= %s", __func__, b64_auth); + + /* MD5 digest of auth:nonce:notification (empty nonce) */ + char *complete = g_strdup_printf("%s::%s", b64_auth, b64_san); + smlSafeCFree(&b64_auth); + smlSafeCFree(&b64_san); + smlMD5GetDigest (complete, strlen(complete), digest); + smlSafeCFree(&complete); + smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) complete", __func__); + + /* copy digest to buffer */ + memcpy(*data, digest, 16); + smlTrace(TRACE_INTERNAL, "%s: md5(auth::san) copied to san", __func__); + + /* debug */ + char *hex = smlPrintHex(*data, *size); smlTrace(TRACE_INTERNAL, "San packet assembled: %s", hex); smlSafeCFree(&hex); |