mech-cram-md5.c revision a8e132559a7ebe54c8269d79ce29fa3338c76199
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen/* Copyright (C) 2002,2003 Timo Sirainen / Joshua Goodall */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen/* CRAM-MD5 SASL authentication, see RFC-2195
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen Joshua Goodall <joshua@roughtrade.net> */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen /* requested: */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen /* received: */
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen unsigned long maxbuf;
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainenstatic const char *get_cram_challenge(void)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen return t_strdup_printf("<%s.%s@%s>", (const char *)buf,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool verify_credentials(struct cram_auth_request *request,
517d1e7142d57299c733b30423e35e7e1f8d01d6Timo Sirainen if (hex_to_binary(credentials, context_digest_buf) < 0) {
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_error(&request->auth_request, "cram-md5",
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "passdb credentials are not in hex");
edf7428147facc11ddb43b9a874a99b96486d42dTimo Sirainen hmac_md5_set_cram_context(&ctx, context_digest);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen hmac_md5_update(&ctx, request->challenge, strlen(request->challenge));
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (memcmp(response_hex, request->response, 32) != 0) {
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_info(&request->auth_request, "cram-md5",
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen "password mismatch");
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool parse_cram_response(struct cram_auth_request *request,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char **error_r)
3a734c9c3efd87864d1ad860826fd4e787457bedTimo Sirainen /* <username> SPACE <response>. Username may contain spaces, so assume
3a734c9c3efd87864d1ad860826fd4e787457bedTimo Sirainen the rightmost space is the response separator. */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->username = p_strndup(request->pool, data, space);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen p_strndup(request->pool, data + space, size - space);
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainenstatic void credentials_callback(enum passdb_result result,
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainenmech_cram_md5_auth_continue(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (parse_cram_response(request, data, data_size, &error)) {
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen if (auth_request_set_username(auth_request, request->username,
49e513d090753ccbf95560b2f3a21f081a5b6c51Timo Sirainen auth_request_log_info(auth_request, "cram-md5", "%s", error);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenmech_cram_md5_auth_initial(struct auth_request *auth_request,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request->challenge = p_strdup(request->pool, get_cram_challenge());
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
78ed6a99e980228a75fa59cff84327dc0ea82857Timo Sirainen request->challenge, strlen(request->challenge));
4ac5448461b63de9637de839fbc611a3d503287cTimo Sirainenstatic struct auth_request *mech_cram_md5_auth_new(void)
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen pool = pool_alloconly_create("cram_md5_auth_request", 2048);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen request = p_new(pool, struct cram_auth_request, 1);