client-authenticate.c revision 9eb98cb3f9139afaaaf84b789b70abd1d0890932
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenconst char *client_authenticate_get_capabilities(int secured)
2b3b0df76184799317584b596af8df5afec3ebddTimo Sirainen auth_mechs = auth_client_get_available_mechs(auth_client);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen for (i = 0; i < AUTH_MECH_COUNT; i++) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((auth_mechs & auth_mech_desc[i].mech) == 0)
2b3b0df76184799317584b596af8df5afec3ebddTimo Sirainen continue; /* not available */
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen /* a) transport is secured
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen b) auth mechanism isn't plaintext
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen c) we allow insecure authentication
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen - but don't advertise AUTH=PLAIN, as RFC 2595 requires
d244c6cadd5f077f5d0f1e00c3652d0108a2d908Timo Sirainen if (secured || !auth_mech_desc[i].plaintext ||
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen cached_capability = i_strdup_empty(str_c(str));
baf1148108b7d9739626b47cc57298c36929586aTimo Sirainenstatic struct auth_mech_desc *auth_mech_find(const char *name)
baf1148108b7d9739626b47cc57298c36929586aTimo Sirainen for (i = 0; i < AUTH_MECH_COUNT; i++) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen strcasecmp(auth_mech_desc[i].name, name) == 0)
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainenstatic void client_auth_abort(struct imap_client *client, const char *msg)
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen auth_client_request_abort(client->common.auth_request);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen "NO Authentication failed.");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen /* get back to normal client input */
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client->common.io = client->common.fd == -1 ? NULL :
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen io_add(client->common.fd, IO_READ, client_input, client);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void master_callback(struct client *_client, int success)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct imap_client *client = (struct imap_client *) _client;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen reason = t_strconcat("Login: ", client->common.virtual_user,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen reason = t_strconcat("Internal login failure: ",
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen client_send_line(client, "* BYE Internal login failure.");
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic void client_send_auth_data(struct imap_client *client,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_send(client->output, buffer_get_data(buf, NULL),
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic void login_callback(struct auth_request *request,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen const void *ptr;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen switch (auth_callback(request, reply, data, &client->common,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* login failed */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* continue */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen ptr = buffer_get_data(client->plain_login, &size);
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen auth_client_request_continue(request, ptr, size);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* success, we should be able to log in. if we fail, just
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen disconnect the client. */
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainenint cmd_login(struct imap_client *client, struct imap_arg *args)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* two arguments: username and password */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (!client->secured && disable_plaintext_auth) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen "but your client sent password in plaintext anyway. "
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen "If anyone was listening, the password was exposed.");
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen "NO Plaintext authentication disabled.");
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen buffer_append(client->plain_login, user, strlen(user));
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen buffer_append(client->plain_login, pass, strlen(pass));
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen auth_client_request_new(auth_client, AUTH_MECH_PLAIN,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* don't read any input from client until login is finished */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenstatic void authenticate_callback(struct auth_request *request,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen switch (auth_callback(request, reply, data, &client->common,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* login failed */
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* continue */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen client_send_auth_data(client, data, reply->data_size);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* success, we should be able to log in. if we fail, just
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen disconnect the client. */
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen if (i_stream_next_line(client->input) == NULL)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* @UNSAFE */
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen client_auth_abort(client, "Authentication aborted");
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(), linelen);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (base64_decode((const unsigned char *) line, linelen,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen client_auth_abort(client, "Invalid base64 data");
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen } else if (client->common.auth_request == NULL) {
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainen client_auth_abort(client, "Don't send unrequested data");
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainen auth_client_request_continue(client->common.auth_request,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* clear sensitive data */
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen safe_memset(buffer_free_without_data(buf), 0, bufsize);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenint cmd_authenticate(struct imap_client *client, struct imap_arg *args)
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* we want only one argument: authentication mechanism name */
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen "NO Unsupported authentication mechanism.");
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (!client->secured && mech->plaintext && disable_plaintext_auth) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen "NO Plaintext authentication disabled.");
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen auth_client_request_new(auth_client, mech->mech,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* following input data will go to authentication */