54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen * APOP (RFC-1460) authentication mechanism.
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
e074ffeaee1ce283bd42f167c6810e3d013f8218Timo Sirainen * This software is released under the MIT license.
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen /* requested: */
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen /* received: */
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool verify_credentials(struct apop_auth_request *request,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size)
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen md5_update(&ctx, request->challenge, strlen(request->challenge));
ace06232cfa0e99ecca1040e8553b3216d025768Timo Sirainen return mem_equals_timing_safe(digest, request->response_digest, 16);
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainenapop_credentials_callback(enum passdb_result result,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen const unsigned char *credentials, size_t size,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen if (verify_credentials(request, credentials, size))
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainenmech_apop_auth_initial(struct auth_request *auth_request,
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen const unsigned char *tmp, *end, *username = NULL;
5d8969b92762691fd3e326f05992e7d64fd42675Timo Sirainen /* pop3-login handles sending the challenge and getting the response.
5d8969b92762691fd3e326f05992e7d64fd42675Timo Sirainen Our input here is: <challenge> \0 <username> \0 <response> */
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen /* Should never happen */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
d47cf089bee2ea1f5a5a791eb5fc5e25884ad9d0Aki Tuomi "no initial response");
5d8969b92762691fd3e326f05992e7d64fd42675Timo Sirainen /* get the challenge */
5d8969b92762691fd3e326f05992e7d64fd42675Timo Sirainen request->challenge = p_strdup_until(request->pool, data, tmp);
5e5c6dc798670afe6b717529e0df2c94879fd112Timo Sirainen /* get the username */
4ad29d683940a58dbdbeb9ec6bb63536a61acd76Aki Tuomi /* should never happen */
4ad29d683940a58dbdbeb9ec6bb63536a61acd76Aki Tuomi auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
4ad29d683940a58dbdbeb9ec6bb63536a61acd76Aki Tuomi "malformed data");
5e5c6dc798670afe6b717529e0df2c94879fd112Timo Sirainen /* Should never happen */
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen "malformed data");
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen /* the challenge must begin with trusted unique ID. we trust only
54bde50b7d791bd8c3d2a6581f8a4ff26d9f0834Timo Sirainen ourself, so make sure it matches our connection specific UID
9eedd38c2985596fb692dcca62193379d34c4c5bTimo Sirainen which we told to client in handshake. Also require a timestamp
9eedd38c2985596fb692dcca62193379d34c4c5bTimo Sirainen which is later than this process's start time. */
5d8969b92762691fd3e326f05992e7d64fd42675Timo Sirainen if (sscanf(request->challenge, "<%lx.%lx.%lx.",
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "invalid challenge");
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen if (!auth_request_set_username(auth_request, (const char *)username,
6135260095e1704ed6edff9d00bdfc043c11429cTimo Sirainen auth_request_log_info(auth_request, AUTH_SUBSYS_MECH, "%s", error);
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen auth_request_lookup_credentials(auth_request, "PLAIN",
4ac5448461b63de9637de839fbc611a3d503287cTimo Sirainenstatic struct auth_request *mech_apop_auth_new(void)
1b81b28b2e7856748cffd7d01052a944b6c80b23Timo Sirainen pool = pool_alloconly_create(MEMPOOL_GROWING"apop_auth_request", 2048);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = p_new(pool, struct apop_auth_request, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .flags = MECH_SEC_PRIVATE | MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,