<commit_before>/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */

#include "login-common.h"
#include "base64.h"
#include "buffer.h"
#include "hex-binary.h"
#include "istream.h"
#include "write-full.h"
#include "strescape.h"
#include "str-sanitize.h"
#include "anvil-client.h"
#include "auth-client.h"
#include "ssl-proxy.h"
#include "master-service.h"
#include "master-interface.h"
#include "master-auth.h"
#include "client-common.h"

#include <stdlib.h>
#include <unistd.h>

#define ERR_TOO_MANY_USERIP_CONNECTIONS \
	"Maximum number of connections from user+IP exceeded " \
	"(mail_max_userip_connections=%u)"

struct anvil_request {
	struct client *client;
	unsigned int auth_pid, auth_id;
	unsigned char cookie[MASTER_AUTH_COOKIE_SIZE];
};

const struct auth_mech_desc *
sasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
{
	const struct auth_mech_desc *mech;
	struct auth_mech_desc *ret_mech;
	unsigned int i, j, count;

	mech = auth_client_get_available_mechs(auth_client, &count);
	if (count == 0) {
		*count_r = 0;
		return NULL;
	}

	ret_mech = t_new(struct auth_mech_desc, count);
	for (i = j = 0; i < count; i++) {
		/* a) transport is secured
		   b) auth mechanism isn't plaintext
		   c) we allow insecure authentication
		*/
		if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
		    (client->secured || !client->set->disable_plaintext_auth ||
		     (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
			ret_mech[j++] = mech[i];
	}
	*count_r = j;
	return ret_mech;
}

static enum auth_request_flags
client_get_auth_flags(struct client *client)
{
        enum auth_request_flags auth_flags = 0;

	if (client->ssl_proxy != NULL &&
	    ssl_proxy_has_valid_client_cert(client->ssl_proxy))
		auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
	if (client->secured)
		auth_flags |= AUTH_REQUEST_FLAG_SECURED;
	return auth_flags;
}

static void
call_client_callback(struct client *client, enum sasl_server_reply reply,
		     const char *data, const char *const *args)
{
	sasl_server_callback_t *sasl_callback;

	i_assert(reply != SASL_SERVER_REPLY_CONTINUE);

	sasl_callback = client->sasl_callback;
	client->sasl_callback = NULL;

	sasl_callback(client, reply, data, args);
	/* NOTE: client may be destroyed now */
}

static void
master_auth_callback(const struct master_auth_reply *reply, void *context)
{
	struct client *client = context;
	enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
	const char *data = NULL;

	client->master_tag = 0;
	client->authenticating = FALSE;
	if (reply != NULL) {
		switch (reply->status) {
		case MASTER_AUTH_STATUS_OK:
			sasl_reply = SASL_SERVER_REPLY_SUCCESS;
			break;
		case MASTER_AUTH_STATUS_INTERNAL_ERROR:
			sasl_reply = SASL_SERVER_REPLY_MASTER_ABORTED;
			break;
		}
	}
	client->mail_pid = reply->mail_pid;
	call_client_callback(client, sasl_reply, data, NULL);
}

static void master_send_request(struct anvil_request *anvil_request)
{
	struct client *client = anvil_request->client;
	struct master_auth_request req;
	const unsigned char *data;
	size_t size;
	buffer_t *buf;

	memset(&req, 0, sizeof(req));
	req.auth_pid = anvil_request->auth_pid;
	req.auth_id = anvil_request->auth_id;
	req.local_ip = client->local_ip;
	req.remote_ip = client->ip;
	req.client_pid = getpid();
	if (client->ssl_proxy != NULL &&
	    ssl_proxy_get_compression(client->ssl_proxy))<commit_msg>login: Crashfix on error conditions.<commit_after>/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */

#include "login-common.h"
#include "base64.h"
#include "buffer.h"
#include "hex-binary.h"
#include "istream.h"
#include "write-full.h"
#include "strescape.h"
#include "str-sanitize.h"
#include "anvil-client.h"
#include "auth-client.h"
#include "ssl-proxy.h"
#include "master-service.h"
#include "master-interface.h"
#include "master-auth.h"
#include "client-common.h"

#include <stdlib.h>
#include <unistd.h>

#define ERR_TOO_MANY_USERIP_CONNECTIONS \
	"Maximum number of connections from user+IP exceeded " \
	"(mail_max_userip_connections=%u)"

struct anvil_request {
	struct client *client;
	unsigned int auth_pid, auth_id;
	unsigned char cookie[MASTER_AUTH_COOKIE_SIZE];
};

const struct auth_mech_desc *
sasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
{
	const struct auth_mech_desc *mech;
	struct auth_mech_desc *ret_mech;
	unsigned int i, j, count;

	mech = auth_client_get_available_mechs(auth_client, &count);
	if (count == 0) {
		*count_r = 0;
		return NULL;
	}

	ret_mech = t_new(struct auth_mech_desc, count);
	for (i = j = 0; i < count; i++) {
		/* a) transport is secured
		   b) auth mechanism isn't plaintext
		   c) we allow insecure authentication
		*/
		if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
		    (client->secured || !client->set->disable_plaintext_auth ||
		     (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
			ret_mech[j++] = mech[i];
	}
	*count_r = j;
	return ret_mech;
}

static enum auth_request_flags
client_get_auth_flags(struct client *client)
{
        enum auth_request_flags auth_flags = 0;

	if (client->ssl_proxy != NULL &&
	    ssl_proxy_has_valid_client_cert(client->ssl_proxy))
		auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
	if (client->secured)
		auth_flags |= AUTH_REQUEST_FLAG_SECURED;
	return auth_flags;
}

static void
call_client_callback(struct client *client, enum sasl_server_reply reply,
		     const char *data, const char *const *args)
{
	sasl_server_callback_t *sasl_callback;

	i_assert(reply != SASL_SERVER_REPLY_CONTINUE);

	sasl_callback = client->sasl_callback;
	client->sasl_callback = NULL;

	sasl_callback(client, reply, data, args);
	/* NOTE: client may be destroyed now */
}

static void
master_auth_callback(const struct master_auth_reply *reply, void *context)
{
	struct client *client = context;
	enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
	const char *data = NULL;

	client->master_tag = 0;
	client->authenticating = FALSE;
	if (reply != NULL) {
		switch (reply->status) {
		case MASTER_AUTH_STATUS_OK:
			sasl_reply = SASL_SERVER_REPLY_SUCCESS;
			break;
		case MASTER_AUTH_STATUS_INTERNAL_ERROR:
			sasl_reply = SASL_SERVER_REPLY_MASTER_ABORTED;
			break;
		}
		client->mail_pid = reply->mail_pid;
	}
	call_client_callback(client, sasl_reply, data, NULL);
}

static void master_send_request(struct anvil_request *anvil_request)
{
	struct client *client = anvil_request->client;
	struct master_auth_request req;
	const unsigned char *data;
	size_t size;
	buffer_t *buf;

	memset(&req, 0, sizeof(req));
	req.auth_pid = anvil_request->auth_pid;
	req.auth_id = anvil_request->auth_id;
	req.local_ip = client->local_ip;
	req.remote_ip = client->ip;
	req.client_pid = getpid();
	if (client->ssl_proxy != NULL &&
	    ssl_proxy_get_compression(client->ssl_proxy))
{'fraction_non_alphanumeric': 0.11586975652684071, 'fraction_numerical': 0.005280140803754767, 'mean_word_length': 5.1047448522829, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2244616', 'n_tokens_mistral': 2671, 'n_tokens_neox': 2535, 'n_words': 553}