/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
#include "auth-common.h"
#include "buffer.h"
#include "hash.h"
#include "llist.h"
#include "str.h"
#include "strescape.h"
#include "str-sanitize.h"
#include "hostpid.h"
#include "hex-binary.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
#include "ostream.h"
#include "ipwd.h"
#include "master-service.h"
#include "userdb.h"
#include "userdb-blocking.h"
#include "master-interface.h"
#include "passdb-cache.h"
#include "auth-request-handler.h"
#include "auth-client-connection.h"
#include "auth-master-connection.h"
#include <unistd.h>
struct master_userdb_request {
};
struct master_list_iter_ctx {
bool failed;
};
static const char *
const char *str)
{
unsigned int i;
return str;
/* hide all parameters that have "pass" in their key */
*p2 = '\0';
}
}
}
{
i_debug("master userdb out: %s",
}
}
static bool
{
/* <id> <client-pid> <client-id> <cookie> [<parameters>] */
i_error("BUG: Master sent broken REQUEST");
return FALSE;
}
i_error("BUG: Master sent broken REQUEST cookie");
return FALSE;
}
if (client_conn == NULL) {
i_error("Master requested auth for nonexistent client %u",
i_error("Master requested auth for client %u with invalid cookie",
} else if (!auth_request_handler_master_request(
i_error("Master requested auth for non-login client %u",
}
return TRUE;
}
static bool
{
const char *const *list;
unsigned int count;
/* <id> [<user> [<user> [..]] */
i_error("BUG: doveadm sent broken CACHE-FLUSH");
return FALSE;
}
if (passdb_cache == NULL) {
/* cache disabled */
count = 0;
/* flush the whole cache */
} else {
}
return TRUE;
}
static int
const char **error_r)
{
unsigned int id;
/* <id> <userid> [<parameters>] */
return -1;
}
arg = "";
} else {
arg++;
}
}
return -1;
}
return 0;
}
return 1;
}
static int
{
if (conn->userdb_restricted_uid == 0)
return 0;
reason = "userdb reply doesn't contain uid";
reason = "userdb reply contains invalid uid";
"userdb uid (%s) doesn't match peer uid (%s)",
} else {
return 0;
}
"client doesn't have lookup permissions for this user: %s "
"(to bypass this check, set: service auth { unix_listener %s { mode=0777 } })",
return -1;
}
static void
struct auth_request *auth_request)
{
const char *value;
if (result == USERDB_RESULT_OK) {
if (user_verify_restricted_uid(auth_request) < 0)
}
switch (result) {
if (auth_request->userdb_lookup_tempfailed) {
"reason");
}
break;
break;
case USERDB_RESULT_OK:
break;
}
i_debug("userdb out: %s",
}
}
static bool
{
const char *error;
int ret;
&auth_request, &error);
if (ret <= 0) {
if (ret < 0)
return FALSE;
} else {
}
return TRUE;
}
enum passdb_result result)
{
switch (result) {
case PASSDB_RESULT_OK:
break;
}
str, AUTH_FIELD_FLAG_HIDDEN, 0);
}
break;
break;
case PASSDB_RESULT_NEXT:
break;
auth_request->id);
break;
}
}
static void
{
}
static void
const unsigned char *credentials ATTR_UNUSED,
struct auth_request *auth_request)
{
int ret;
if (result != PASSDB_RESULT_OK)
else {
if (ret == 0)
return;
if (ret < 0)
}
}
{
const char *namestr;
namestr = "";
else
return t_strdup_printf("%s mode=0666, but not owned by UID %lu%s",
(unsigned long)conn->userdb_restricted_uid,
namestr);
}
static bool
{
const char *error;
int ret;
&auth_request, &error);
if (ret <= 0) {
if (ret < 0)
return FALSE;
uchar_empty_ptr, 0, auth_request);
} else if (conn->userdb_restricted_uid != 0) {
/* no permissions to do this lookup */
"Auth client doesn't have permissions to do "
uchar_empty_ptr, 0, auth_request);
} else {
}
return TRUE;
}
{
}
{
int ret;
return 1;
}
if (ret > 0) {
}
return 1;
}
{
int ret;
do {
/* iteration is finished */
const char *str;
return;
}
/* continue iterating next userdb */
return;
}
T_BEGIN {
const char *str;
} T_END;
if (ret < 0) {
/* disconnected, don't bother finishing */
return;
}
else
}
static bool
{
unsigned int id;
/* <id> [<parameters>] */
i_error("BUG: Master sent broken LIST");
return FALSE;
}
list++;
i_error("Auth client is already iterating users");
return TRUE;
}
if (conn->userdb_restricted_uid != 0) {
i_error("Auth client doesn't have permissions to list users: %s",
return TRUE;
}
i_error("Trying to iterate users, but userdbs don't support it");
return TRUE;
}
arg = "";
} else {
arg++;
}
/* username mask */
}
}
/* rest of the code doesn't like NULL user or service */
return TRUE;
}
static bool
{
if (!conn->userdb_only) {
i_error("Authentication client trying to connect to "
"master socket");
return FALSE;
}
}
i_error("BUG: Unknown command in %s socket: %s",
return FALSE;
}
{
char *line;
bool ret;
case 0:
return;
case -1:
/* disconnected */
return;
case -2:
/* buffer full */
i_error("BUG: Master sent us more than %d bytes",
(int)MAX_INBUF_SIZE);
return;
}
if (!conn->version_received) {
return;
/* make sure the major version matches */
i_error("Master not compatible with this server "
"(mixed old and new binaries?)");
return;
}
}
T_BEGIN {
} T_END;
if (!ret) {
return;
}
}
}
{
/* transmit error, probably master died */
return 1;
}
/* allow input again */
}
return 1;
}
static int
{
return 0;
/* figure out what permissions we want to give to this client */
/* permissions were already restricted by the socket
permissions. also +x bit indicates that we shouldn't do
any permission checks. */
return 0;
}
i_error("userdb connection: Failed to get peer's credentials");
return -1;
}
/* full permissions */
return 0;
} else {
/* restrict permissions: return only lookups whose returned
uid matches the peer's uid */
return 0;
}
}
struct auth_master_connection *
bool userdb_only)
{
const char *line;
my_pid);
return NULL;
}
return conn;
}
{
return;
}
{
}
{
return;
}
void auth_master_connections_destroy_all(void)
{
while (auth_master_connections != NULL) {
}
}