{"action":"created","issue":{"url":"https://api.github.com/repos/libressl-portable/openbsd/issues/47","labels_url":"https://api.github.com/repos/libressl-portable/openbsd/issues/47/labels{/name}","comments_url":"https://api.github.com/repos/libressl-portable/openbsd/issues/47/comments","events_url":"https://api.github.com/repos/libressl-portable/openbsd/issues/47/events","html_url":"https://github.com/libressl-portable/openbsd/pull/47","id":106226002,"number":47,"title":"libtls: Support OCSP","user":{"login":"markokr","id":49397,"avatar_url":"https://avatars.githubusercontent.com/u/49397?v=3","gravatar_id":"","url":"https://api.github.com/users/markokr","html_url":"https://github.com/markokr","followers_url":"https://api.github.com/users/markokr/followers","following_url":"https://api.github.com/users/markokr/following{/other_user}","gists_url":"https://api.github.com/users/markokr/gists{/gist_id}","starred_url":"https://api.github.com/users/markokr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markokr/subscriptions","organizations_url":"https://api.github.com/users/markokr/orgs","repos_url":"https://api.github.com/users/markokr/repos","events_url":"https://api.github.com/users/markokr/events{/privacy}","received_events_url":"https://api.github.com/users/markokr/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-09-13T16:33:35Z","updated_at":"2015-09-13T16:56:47Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/libressl-portable/openbsd/pulls/47","html_url":"https://github.com/libressl-portable/openbsd/pull/47","diff_url":"https://github.com/libressl-portable/openbsd/pull/47.diff","patch_url":"https://github.com/libressl-portable/openbsd/pull/47.patch"},"body":"Here is support for stapling for both client and server,\r\nplus API to launch OCSP network requests.\r\n\r\n1) Stapling\r\n\r\n* Client requests and verifies by default.\r\n\r\n* Server attaches stapling response, if configured.  Config API:\r\n```\r\nint tls_config_set_ocsp_stapling_file(struct tls_config *cf, const char *fn);\r\nint tls_config_set_ocsp_stapling_mem(struct tls_config *cf, const uint8_t *blob, size_t len);\r\n```\r\nFile is loaded on each request.  Some sort of cronjob can be set up to\r\nupdate it periodically.  File and mem is not checked in any way, assumes\r\nadmin has set it up properly.  Note that network requests *do* validate\r\nserver response.\r\n\r\n2) Network API\r\n```\r\nint tls_ocsp_refresh_stapling(struct tls **ocsp_ctx_p, int *async_fd_p, struct tls_config *config);\r\nint tls_ocsp_check_peer(struct tls **ocsp_ctx_p, int *async_fd_p, struct tls *client);\r\n```\r\ntls_ocsp_refresh_stapling() loads response over network and attaches\r\nto config.  Returns TLS_NO_OCSP if cert has no ocsp urls.\r\n\r\ntls_ocsp_check_peer() verifies peer cert over network.  Returns\r\nTLS_NO_OCSP if cert has no OCSP urls set up.\r\n\r\nIf async_fd_p is unset, they operate in sync mode.  If set, a newly\r\ncreated fd will be put there that can be used with any polling method.\r\nAnd they return TLS_WANT_POLLIN / TLS_WANT_POLLOUT as needed. When poll\r\nnotifies about event, the call needs to be repeated.\r\n\r\nIn both async and sync mode they create new \"struct tls\" that can\r\nbe examined for errors and final OCSP details.\r\n\r\n3) Info API.\r\n```\r\nint tls_get_ocsp_info(struct tls *ctx, int *response_status,\r\n                      int *cert_status, int *crl_reason,\r\n                      time_t *this_update, time_t *next_update, time_t *revoction_time,\r\n                      const char **result_text);\r\n```\r\nFor client connection it returns info about stapled OCSP response.\r\nFor network requests it returns what OCSP responder sent.\r\n\r\nSituations:\r\n* No OCSP cert, no stapling from server: returns TLS_NO_OCSP,\r\n  fills result_text with \"no-ocsp\"\r\n* Have valid OCSP response with good signature - returns 0.  All fields\r\n  are set.  This does not mean cert is valid, it can still have\r\n  revoked status.  Or responser may have rejected the request.\r\n* OCSP response validation failed, some network error - returns -1.\r\n  *result_text has verification failure message.\r\n  If ctx is OCSP network context, it has error message.  If client\r\n  connection to server, it has some later error.\r\n\r\nresult_text:\r\n  \"no-ocsp\"  - TLS_NO_OCSP\r\n  \"good\", \"unknown\", \"revoked: ...\" - successful result\r\n  \"...\" - error about failure.\r\n\r\n4) Open questions.\r\n\r\nHow should it coordinate with noverifycert(): check and don't report\r\ndon't check, or don't even ask?  Should the OCSP info be visible\r\nor not when noverifycert() is on?\r\n\r\nThe ->ocsp_result field usage is slightly weird but necessary:\r\nit tracks whether there was any OCSP activity at all.  ocsp_info\r\nis set only on sucessful response.  Also, OCSP errors during\r\nstapling check will be lost, it will track them.\r\n\r\n5) Notes.\r\n\r\n* Although stapling could work without network requests, the\r\n  tls_ocsp_refresh_stapling() makes it actually usable.\r\n\r\n* Main bonus of tls_ocsp_check_peer() is that it makes possible\r\n  to test the code - both server refresh and actual verification -\r\n  against normal public servers.  So it's worth having on purely\r\n  testability grounds.\r\n\r\n* No client ever should make network OCSP request for each new\r\n  connection.  Or server that checks client cert.  Instead OCSP\r\n  responses should be cached, and request is made when cache\r\n  expires.  So the tls_ocsp_check_peer() should not be integrated\r\n  into basic tls_connect().  libtls could give"},"comment":{"url":"https://api.github.com/repos/libressl-portable/openbsd/issues/comments/139894359","html_url":"https://github.com/libressl-portable/openbsd/pull/47#issuecomment-139894359","issue_url":"https://api.github.com/repos/libressl-portable/openbsd/issues/47","id":139894359,"user":{"login":"markokr","id":49397,"avatar_url":"https://avatars.githubusercontent.com/u/49397?v=3","gravatar_id":"","url":"https://api.github.com/users/markokr","html_url":"https://github.com/markokr","followers_url":"https://api.github.com/users/markokr/followers","following_url":"https://api.github.com/users/markokr/following{/other_user}","gists_url":"https://api.github.com/users/markokr/gists{/gist_id}","starred_url":"https://api.github.com/users/markokr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/markokr/subscriptions","organizations_url":"https://api.github.com/users/markokr/orgs","repos_url":"https://api.github.com/users/markokr/repos","events_url":"https://api.github.com/users/markokr/events{/privacy}","received_events_url":"https://api.github.com/users/markokr/received_events","type":"User","site_admin":false},"created_at":"2015-09-13T16:56:47Z","updated_at":"2015-09-13T16:56:47Z","body":"Well, ATM it handles both http: and https: responders.  And uses OCSP http helper functions that use bio.\r\n\r\nUnless you have nice http(s) library I think it would be simpler to keep using the libssl helpers."}}