auth-worker-client.c revision 0af3274706d337b2930bd34f0377f2cc2dbcd18a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (C) 2005 Timo Sirainen */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "common.h"
80c1d98d3638b71e57a39cafa88b9122bf8169c6Timo Sirainen#include "ioloop.h"
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen#include "network.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen#include "auth-request.h"
50031a6b36a6051512bd18f39e4bbabe54acf565Timo Sirainen#include "auth-worker-client.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define OUTBUF_THROTTLE_SIZE (1024*10)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct auth_worker_client {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int refcount;
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen struct auth *auth;
8887bf3757d51d73887dd20b1db3334d867d3817Timo Sirainen int fd;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen struct io *io;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen struct istream *input;
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen struct ostream *output;
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen};
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainenstatic void auth_worker_client_unref(struct auth_worker_client *client);
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainenstatic void
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainenauth_worker_client_check_throttle(struct auth_worker_client *client)
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen{
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen if (o_stream_get_buffer_used_size(client->output) >=
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen OUTBUF_THROTTLE_SIZE) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* stop reading new requests until client has read the pending
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen replies. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->io != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_remove(client->io);
b7b81543899e306c71e6152516d8698416162bcbTimo Sirainen client->io = NULL;
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen }
6ec7cf71ccd0eed1f9cc1b0bda8960796b04160bTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainenstatic struct auth_request *
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainenworker_auth_request_new(struct auth_worker_client *client, unsigned int id,
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen const char *args)
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen{
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen struct auth_request *auth_request;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key, *value, *const *tmp;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request = auth_request_new_dummy(client->auth);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->refcount++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->context = client;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->id = id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (tmp = t_strsplit(args, "\t"); *tmp != NULL; tmp++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value = strchr(*tmp, '=');
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (value == NULL)
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen continue;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen key = t_strdup_until(*tmp, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen value++;
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen if (strcmp(key, "user") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->user =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(auth_request->pool, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(key, "service") == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->service =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(auth_request->pool, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strcmp(key, "lip") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen net_addr2ip(value, &auth_request->local_ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else if (strcmp(key, "rip") == 0)
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen net_addr2ip(value, &auth_request->remote_ip);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return auth_request;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void verify_plain_callback(enum passdb_result result,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_request *request)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen struct auth_worker_client *client = request->context;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen string_t *str;
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen str = t_str_new(64);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "%u\t", request->id);
b84451fa6ada675ae504725702e0815967124cbbTimo Sirainen
b84451fa6ada675ae504725702e0815967124cbbTimo Sirainen if (result != PASSDB_RESULT_OK)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(str, "FAIL\t%d", result);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen else {
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen str_append(str, "OK\t");
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (request->passdb_password != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append(str, request->passdb_password);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, '\t');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (request->extra_fields != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_str(str, request->extra_fields);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen auth_worker_client_check_throttle(client);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen auth_worker_client_unref(client);
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic void
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenauth_worker_handle_passv(struct auth_worker_client *client,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen unsigned int id, const char *args)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen{
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen /* verify plaintext password */
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen struct auth_request *auth_request;
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen const char *password;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen unsigned int num;
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen num = atoi(t_strcut(args, '\t'));
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen args = strchr(args, '\t');
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen if (args == NULL) {
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSV");
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen return;
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen }
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen args++;
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen password = t_strcut(args, '\t');
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen args = strchr(args, '\t');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (args != NULL) args++;
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen auth_request->mech_password =
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen p_strdup(auth_request->pool, password);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen for (; num > 0; num++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->passdb = auth_request->passdb->next;
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen if (auth_request->passdb == NULL) {
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen i_error("BUG: PASSV had invalid passdb num");
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen return;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen }
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen }
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen auth_request->passdb->passdb->verify_plain(auth_request, password,
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen verify_plain_callback);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen}
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainenstatic void
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainenlookup_credentials_callback(enum passdb_result result, const char *credentials,
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen struct auth_request *request)
cfbacf6ea5fb39ae5304e4d95a78d9d4751bdfe1Timo Sirainen{
cfbacf6ea5fb39ae5304e4d95a78d9d4751bdfe1Timo Sirainen struct auth_worker_client *client = request->context;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen string_t *str;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen str = t_str_new(64);
7761758f43d6150be4b07f4c54457ce662f78c4cTimo Sirainen str_printfa(str, "%u\t", request->id);
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen if (result != PASSDB_RESULT_OK)
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen str_printfa(str, "FAIL\t%d", result);
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen else {
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen str_printfa(str, "OK\t{%s}%s\t",
62f4a199b5c9a0862f486cbf18e195cc621bbe25Timo Sirainen passdb_credentials_to_str(request->credentials),
6bc98d3898c475ba7615ba2b016e5142c8b2c09fTimo Sirainen credentials);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (request->extra_fields != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_str(str, request->extra_fields);
659fe5d24825b160cae512538088020d97a60239Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(str, '\n');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client_check_throttle(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client_unref(client);
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen}
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainenstatic void
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenauth_worker_handle_passl(struct auth_worker_client *client,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen unsigned int id, const char *args)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* lookup credentials */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_request *auth_request;
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen const char *credentials_str;
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen enum passdb_credentials credentials;
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen unsigned int num;
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen num = atoi(t_strcut(args, '\t'));
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen args = strchr(args, '\t');
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen if (args == NULL) {
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen i_error("BUG: Auth worker server sent us invalid PASSL");
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen return;
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen }
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen args++;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen credentials_str = t_strcut(args, '\t');
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen args = strchr(args, '\t');
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (args != NULL) args++;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen credentials = atoi(credentials_str);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen for (; num > 0; num++) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen auth_request->passdb = auth_request->passdb->next;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (auth_request->passdb == NULL) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen i_error("BUG: PASSL had invalid passdb num");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->passdb->passdb->
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookup_credentials(auth_request, credentials,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookup_credentials_callback);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainenlookup_user_callback(const char *result, struct auth_request *auth_request)
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen{
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen struct auth_worker_client *client = auth_request->context;
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen string_t *str;
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen str = t_str_new(64);
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen str_printfa(str, "%u\t", auth_request->id);
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen if (result != NULL)
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen str_append(str, result);
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen str_append_c(str, '\n');
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen o_stream_send(client->output, str_data(str), str_len(str));
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen auth_worker_client_check_throttle(client);
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen auth_worker_client_unref(client);
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen}
41e6eb07b411ea58352ba9d2cc8cf340325d49f3Timo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_worker_handle_user(struct auth_worker_client *client,
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen unsigned int id, const char *args)
4d4d585520538a752e9f0a4a1c019a2918f52e56Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* lookup user */
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen struct auth_request *auth_request;
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen unsigned int num;
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen num = atoi(t_strcut(args, '\t'));
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen args = strchr(args, '\t');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (args != NULL) args++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen auth_request = worker_auth_request_new(client, id, args);
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen for (; num > 0; num++) {
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen auth_request->userdb = auth_request->userdb->next;
d30da25fb6be1f1c667d93767c9194000194b618Timo Sirainen if (auth_request->userdb == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("BUG: USER had invalid userdb num");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_request->userdb->userdb->
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lookup(auth_request, lookup_user_callback);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_worker_handle_line(struct auth_worker_client *client, const char *line)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen{
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen const char *p;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen unsigned int id;
ec77cd41241208345efd51c1fcce9030be30aa9bTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p = strchr(line, '\t');
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (p == NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen id = (unsigned int)strtoul(t_strdup_until(line, p), NULL, 10);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen line = p + 1;
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen if (strncmp(line, "PASSV\t", 6) == 0)
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen auth_worker_handle_passv(client, id, line + 6);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen else if (strncmp(line, "PASSL\t", 6) == 0)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen auth_worker_handle_passl(client, id, line + 6);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen else if (strncmp(line, "USER\t", 5) == 0)
eac3948d67eff8623d51aeaea9eca582f3aec677Timo Sirainen auth_worker_handle_user(client, id, line + 5);
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen return TRUE;
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen}
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainenstatic void auth_worker_input(void *context)
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen{
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen struct auth_worker_client *client = context;
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen char *line;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen int ret;
48136ae5a0eb49daa44e343553f3688a500307e2Timo Sirainen
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen switch (i_stream_read(client->input)) {
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen case 0:
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen return;
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen case -1:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* disconnected */
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen auth_worker_client_destroy(client);
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen return;
97735b96d442568f65efa20f8c292a496498c17bTimo Sirainen case -2:
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen /* buffer full */
09c3a491f4f6ccebe290c7709bdc0d79a187610bTimo Sirainen i_error("BUG: Auth worker server sent us more than %d bytes",
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen (int)AUTH_WORKER_MAX_LINE_LENGTH);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen auth_worker_client_destroy(client);
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen return;
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->refcount++;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((line = i_stream_next_line(client->input)) != NULL) {
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen t_push();
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen ret = auth_worker_handle_line(client, line);
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen if (!ret) {
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen auth_worker_client_destroy(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen }
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen }
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen auth_worker_client_unref(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainenstatic int auth_worker_output(void *context)
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen{
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen struct auth_worker_client *client = context;
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen if (o_stream_flush(client->output) < 0) {
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen auth_worker_client_destroy(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen if (o_stream_get_buffer_used_size(client->output) <=
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen OUTBUF_THROTTLE_SIZE/3 && client->io == NULL) {
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen /* allow input again */
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen client->io = io_add(client->fd, IO_READ,
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen auth_worker_input, client);
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen }
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen return 1;
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen}
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainenstruct auth_worker_client *
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainenauth_worker_client_create(struct auth *auth, int fd)
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen{
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen struct auth_worker_client *client;
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen client = i_new(struct auth_worker_client, 1);
768b7f5783c8de119d7386321e5d0c72d5c2d9f6Timo Sirainen client->refcount = 1;
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen client->auth = auth;
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen client->fd = fd;
079f54c97145a0a5daa36c37eead3eae91b67a1eTimo Sirainen client->input =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_create_file(fd, default_pool,
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen AUTH_WORKER_MAX_LINE_LENGTH, FALSE);
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen client->output =
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen o_stream_set_flush_callback(client->output, auth_worker_output, client);
3955d6726c939b3b30527c22b70c879fbe78692eTimo Sirainen client->io = io_add(fd, IO_READ, auth_worker_input, client);
3955d6726c939b3b30527c22b70c879fbe78692eTimo Sirainen
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen return client;
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen}
89caf81340a4da959ef18c5f9b9c99824a53066bTimo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainenvoid auth_worker_client_destroy(struct auth_worker_client *client)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (client->fd == -1)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen i_stream_close(client->input);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen o_stream_close(client->output);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->io != NULL) {
685393de106e55b61f754d420e378d05bd462ebbTimo Sirainen io_remove(client->io);
87712707722ef7d73acb065546e61afa4455cd9eTimo Sirainen client->io = NULL;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen }
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen net_disconnect(client->fd);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->fd = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen io_loop_stop(ioloop);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_worker_client_unref(client);
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen}
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainen
5a86309a6c58bdeb9921bf2989aaabaaa04a29abTimo Sirainenstatic void auth_worker_client_unref(struct auth_worker_client *client)
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen{
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (--client->refcount > 0)
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
94a8cb0ee1d85569ad1a2acacd92d3ce22f8a1cbTimo Sirainen i_stream_unref(client->input);
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen o_stream_unref(client->output);
17da42c31202b1b3e7e308121ea17d922c24da1bTimo Sirainen i_free(client);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen