Skip to content

GMimeSignature created and expires are time_t, fail in Y2038 on platforms with 32-bit signed time_t #68

Closed

Description

@dkg

g_mime_signature_{s,g}et_{created,expires} uses time_t.

They are produced from the underlying GPGME gpgme_signature_t object, which indicate that they are unsigned long values.

But time(2) from linux manpages says that time_t is 32-bit signed on some platforms:

On Linux, a call to time() with tloc specified as NULL cannot fail with
the error EOVERFLOW, even on ABIs where time_t is a signed 32-bit inte‐
ger and the clock ticks past the time 2**31 (2038-01-19 03:14:08 UTC,
ignoring leap seconds). (POSIX.1 permits, but does not require, the
EOVERFLOW error in the case where the seconds since the Epoch will not
fit in time_t.) Instead, the behavior on Linux is undefined when the
system time is out of the time_t range. Applications intended to run
after 2038 should use ABIs with time_t wider than 32 bits.

This means that on a platform where long is 32 bits (e.g. x86_64), even though GPGME can correctly report a signature with validity ranges between 2**31 and 2**32 seconds, or (2038-01-19 03:14:08 → 2106-02-07 06:28:16 UTC), GMime wraps those values around into the negative range.

I'm running into this when I use GMime to handle sample S/MIME certificates whose expiration dates are later than Y2038.

Activity

  1. dkg commented on Dec 4, 2019

    @dkg
    ContributorAuthor

    I'm not sure the right fix for this. From a glib perspective, i'd like to see the creation and expiration dates either returned as a GDateTime or a guint64 (microseconds since the epoch).

    As glib documentation says:

    GTimeVal is not year-2038-safe. Use guint64 for representing microseconds since the epoch, or use GDateTime.

    The advantage of guint64 is that the caller doesn't need to worry about invoking g_date_time_free.

    I suppose we could offer both mechanisms, though, and let the caller decide.

  2. dkg commented on Dec 4, 2019

    @dkg
    ContributorAuthor

    #69 is a simple, conservative approach that should at least expose the correct information.

    I haven't written a test for this yet, but simply running g_mime_application_pkcs7_mime_verify() against the following message would probably do it (the signing certificate expires later than Y2038):

    Received: from localhost (localhost [127.0.0.1]); Tue, 26 Nov 2019
     20:11:46 -0400 (UTC-04:00)
    Content-Transfer-Encoding: base64
    Content-Type: application/pkcs7-mime; name="smime.p7m";
     smime-type="signed-data"
    MIME-Version: 1.0
    From: Alice Lovelace <alice@smime.example>
    To: Bob Babbage <bob@smime.example>
    Date: Tue, 26 Nov 2019 20:11:29 -0400
    Subject: The FooCorp contract
    Message-ID: <smime-onepart-signed@protected-headers.example>
    
    MIIHRQYJKoZIhvcNAQcCoIIHNjCCBzICAQExDTALBglghkgBZQMEAgEwggHJBgkq
    hkiG9w0BBwGgggG6BIIBtkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNl
    dD0idXMtYXNjaWkiDQpGcm9tOiBBbGljZSBMb3ZlbGFjZSA8YWxpY2VAc21pbWUu
    ZXhhbXBsZT4NClRvOiBCb2IgQmFiYmFnZSA8Ym9iQHNtaW1lLmV4YW1wbGU+DQpE
    YXRlOiBUdWUsIDI2IE5vdiAyMDE5IDIwOjExOjI5IC0wNDAwDQpTdWJqZWN0OiBU
    aGUgRm9vQ29ycCBjb250cmFjdA0KTWVzc2FnZS1JRDogPHNtaW1lLW9uZXBhcnQt
    c2lnbmVkQHByb3RlY3RlZC1oZWFkZXJzLmV4YW1wbGU+DQoNCkJvYiwgd2UgbmVl
    ZCB0byBjYW5jZWwgdGhpcyBjb250cmFjdC4NCg0KUGxlYXNlIHN0YXJ0IHRoZSBu
    ZWNlc3NhcnkgcHJvY2Vzc2VzIHRvIG1ha2UgdGhhdCBoYXBwZW4gdG9kYXkuDQoN
    ClRoYW5rcywgQWxpY2UNCi0tIA0KQWxpY2UgTG92ZWxhY2UNClByZXNpZGVudA0K
    T3BlblBHUCBFeGFtcGxlIENvcnANCqCCA3IwggNuMIICVqADAgECAhRngrRZc1JL
    wfRxRxlq8P0RiqpMCzANBgkqhkiG9w0BAQ0FADAtMSswKQYDVQQDEyJTYW1wbGUg
    TEFNUFMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTE5MTEyMDA2NTQxOFoYDzIw
    NTIwOTI3MDY1NDE4WjAZMRcwFQYDVQQDEw5BbGljZSBMb3ZlbGFjZTCCASIwDQYJ
    KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPurfll0bYkDPMkY1kNn2xXsAqHSGVF
    +gWNNk3mbhF6BABhLJqDjei5aLXFE3Rq9/RRNivCMrTipF1XsbMIAKgQqr/GI1Q6
    yN8lfNsK5uU3d9kw5cOyEooGpOGUrvlKMD0LPGDt6MaiJj+KJ2TR73Wd4rfRIIJo
    FMmV9HZkOs+Tvcg8x6SzGhNq18X2HD10MD78eLXKm039obRD+z2JwWvGvrLbNBey
    O5A+aMxmCPXRoP1xrNZWBFgKB+WGYDRXW5CXXChthTwMBXFWf4aBpurKMZAyjK2E
    grQafn6h/DFddQz/NtT6Dr7UhJ2hfFFEW2rYbNsiqQAdllCb4FucWuECAwEAAaOB
    lzCBlDAMBgNVHRMBAf8EAjAAMB4GA1UdEQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1w
    bGUwEwYDVR0lBAwwCgYIKwYBBQUHAwQwDwYDVR0PAQH/BAUDAwegADAdBgNVHQ4E
    FgQUrC5UWqT9VRivLuhmRDjRJdHXAHkwHwYDVR0jBBgwFoAUt1JNc8CIPbLDeloM
    85T394Cid9swDQYJKoZIhvcNAQENBQADggEBAHvqjhjPvKtVIVyleoutwa10jir3
    dooJcQIILM1AunjJ6yHpuuppkc0m3BhwnlOptTKb2EnvSIkTiMY037IBlHWW217Q
    cUpggEozgQm6Yb77aGptRovPi2XToEdpA8K//02I1jur1H1z8HqzVjMeHCqRaG3Z
    r4C2AngGSkb6D4yZkxBX8CjtHAsUon06UxYsGYRcVykgk3Qek9qxPScSX8yai1K7
    7xGcKUCLfIV/JMpv7ysPtXG7Jd62oNnp1T/3+KoP9JlLs5AiPLC13fjeYALPcHVG
    UXEwdIDp1AB/Zu0a6apHQqICncqRhEB4+hompiQHtlp3TqeAWXQbQUc437sxggHZ
    MIIB1QIBATBFMC0xKzApBgNVBAMTIlNhbXBsZSBMQU1QUyBDZXJ0aWZpY2F0ZSBB
    dXRob3JpdHkCFGeCtFlzUkvB9HFHGWrw/RGKqkwLMAsGCWCGSAFlAwQCAaBpMBgG
    CSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE5MTEyNzAw
    MTEyOVowLwYJKoZIhvcNAQkEMSIEILsI9kL3zfZiVOEDjAUWrbjHjGMLoGUwEqYH
    pOA9XZ+QMA0GCSqGSIb3DQEBAQUABIIBAGDat8UYN9MShlKEw3hYVVUk6HKO6Xjp
    rdgCBKpoyoWJy0VJis0xHxaT2gn/+TPu8a5l6RslgeALjMyflzyzAmrqnknQQG8K
    bvbt/MwpU/TxnmxT+2oP9TVmAx/IQOq4pQ35uK7peSPck2CcTvZjHTeVBWcsLVEk
    hELoSD8XFRBo34qdinBzW0/sMlyK1XnlN7khKry1g7uaXcurVqptRA1rWOvCOt72
    aElKG/Q7OoVgHxbUpdzV3Hqe9/UeTRDUqCs++on2pLlA0TA0Pq8RQ0hDHD/p0t41
    1RAT1/RbnGQiVfRilMan+VGT4shokb1RoANy/1rOO9ZKlyWToYdRl9E=
    

    (this example message is from an upcoming revision to draft-autocrypt-lamps-protected-headers)

  3. jstedfast commented on Dec 4, 2019

    @jstedfast
    Owner

    GDateTime uses gint64 seconds from epoch. I'm not sure we need higher resolution than seconds for created/expires timestamps.

    https://developer.gnome.org/glib/stable/glib-GDateTime.html#g-date-time-new-from-unix-local

    That said, I absolutely agree that I'd rather use a gint64 than a GDateTime - especially if someone can easily convert to a GDateTime if that's what they really want.

  4. jstedfast commented on Dec 4, 2019

    @jstedfast
    Owner

    I added get_created64() and get_expires64() instead which does similar casting to get seconds since epoch.

    I can't test this because on MacOS, time_t is 64bit which makes this a non-issue on this platform.

  5. jstedfast commented on Oct 28, 2026

    @jstedfast
    Owner

    This has been fixed in my local 4.0 branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions