~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to src/auth/passdb-dict.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
 
2
 
 
3
#include "auth-common.h"
 
4
#include "passdb.h"
 
5
 
 
6
#include "str.h"
 
7
#include "var-expand.h"
 
8
#include "dict.h"
 
9
#include "password-scheme.h"
 
10
#include "auth-cache.h"
 
11
#include "db-dict.h"
 
12
 
 
13
#include <stdlib.h>
 
14
#include <string.h>
 
15
 
 
16
struct dict_passdb_module {
 
17
        struct passdb_module module;
 
18
 
 
19
        struct dict_connection *conn;
 
20
};
 
21
 
 
22
struct passdb_dict_request {
 
23
        struct auth_request *auth_request;
 
24
        union {
 
25
                verify_plain_callback_t *verify_plain;
 
26
                lookup_credentials_callback_t *lookup_credentials;
 
27
        } callback;
 
28
};
 
29
 
 
30
static int
 
31
dict_query_save_results(struct auth_request *auth_request,
 
32
                        struct dict_connection *conn, const char *result)
 
33
{
 
34
        struct db_dict_value_iter *iter;
 
35
        const char *key, *value, *error;
 
36
 
 
37
        iter = db_dict_value_iter_init(conn, result);
 
38
        while (db_dict_value_iter_next(iter, &key, &value)) {
 
39
                if (value != NULL) {
 
40
                        auth_request_set_field(auth_request, key, value,
 
41
                                               conn->set.default_pass_scheme);
 
42
                }
 
43
        }
 
44
        if (db_dict_value_iter_deinit(&iter, &error) < 0) {
 
45
                auth_request_log_error(auth_request, "dict",
 
46
                        "Value '%s' not in valid %s format: %s",
 
47
                        result, conn->set.value_format, error);
 
48
                return -1;
 
49
        }
 
50
        return 0;
 
51
}
 
52
 
 
53
static enum passdb_result
 
54
passdb_dict_lookup_key(struct auth_request *auth_request,
 
55
                       struct dict_passdb_module *module, const char *key)
 
56
{
 
57
        const char *value;
 
58
        int ret;
 
59
 
 
60
        auth_request_log_debug(auth_request, "dict", "lookup %s", key);
 
61
        ret = dict_lookup(module->conn->dict, pool_datastack_create(),
 
62
                          key, &value);
 
63
        if (ret < 0) {
 
64
                auth_request_log_error(auth_request, "dict", "Lookup failed");
 
65
                return PASSDB_RESULT_INTERNAL_FAILURE;
 
66
        } else if (ret == 0) {
 
67
                auth_request_log_unknown_user(auth_request, "dict");
 
68
                return PASSDB_RESULT_USER_UNKNOWN;
 
69
        } else {
 
70
                auth_request_log_debug(auth_request, "dict",
 
71
                                       "result: %s", value);
 
72
                if (dict_query_save_results(auth_request, module->conn, value) < 0)
 
73
                        return PASSDB_RESULT_INTERNAL_FAILURE;
 
74
 
 
75
                if (auth_request->passdb_password == NULL &&
 
76
                    !auth_fields_exists(auth_request->extra_fields, "nopassword")) {
 
77
                        auth_request_log_info(auth_request, "dict",
 
78
                                "No password returned (and no nopassword)");
 
79
                        return PASSDB_RESULT_PASSWORD_MISMATCH;
 
80
                } else {
 
81
                        return PASSDB_RESULT_OK;
 
82
                }
 
83
        }
 
84
}
 
85
 
 
86
static void passdb_dict_lookup_pass(struct passdb_dict_request *dict_request)
 
87
{
 
88
        struct auth_request *auth_request = dict_request->auth_request;
 
89
        struct passdb_module *_module = auth_request->passdb->passdb;
 
90
        struct dict_passdb_module *module =
 
91
                (struct dict_passdb_module *)_module;
 
92
        string_t *key;
 
93
        const char *password = NULL, *scheme = NULL;
 
94
        enum passdb_result passdb_result;
 
95
        int ret;
 
96
 
 
97
        key = t_str_new(512);
 
98
        str_append(key, DICT_PATH_SHARED);
 
99
        var_expand(key, module->conn->set.password_key,
 
100
                   auth_request_get_var_expand_table(auth_request, NULL));
 
101
 
 
102
        if (*module->conn->set.password_key == '\0') {
 
103
                auth_request_log_error(auth_request, "dict",
 
104
                                       "password_key not specified");
 
105
                passdb_result = PASSDB_RESULT_INTERNAL_FAILURE;
 
106
        } else {
 
107
                passdb_result = passdb_dict_lookup_key(auth_request, module,
 
108
                                                       str_c(key));
 
109
        }
 
110
 
 
111
        if (passdb_result == PASSDB_RESULT_OK) {
 
112
                /* passdb_password may change on the way,
 
113
                   so we'll need to strdup. */
 
114
                password = t_strdup(auth_request->passdb_password);
 
115
                scheme = password_get_scheme(&password);
 
116
                /* auth_request_set_field() sets scheme */
 
117
                i_assert(password == NULL || scheme != NULL);
 
118
        }
 
119
 
 
120
        if (auth_request->credentials_scheme != NULL) {
 
121
                passdb_handle_credentials(passdb_result, password, scheme,
 
122
                        dict_request->callback.lookup_credentials,
 
123
                        auth_request);
 
124
        } else {
 
125
                if (password != NULL) {
 
126
                        ret = auth_request_password_verify(auth_request,
 
127
                                        auth_request->mech_password,
 
128
                                        password, scheme, "dict");
 
129
                        passdb_result = ret > 0 ? PASSDB_RESULT_OK :
 
130
                                PASSDB_RESULT_PASSWORD_MISMATCH;
 
131
                }
 
132
 
 
133
                dict_request->callback.verify_plain(passdb_result,
 
134
                                                    auth_request);
 
135
        }
 
136
}
 
137
 
 
138
static void dict_verify_plain(struct auth_request *request,
 
139
                              const char *password ATTR_UNUSED,
 
140
                              verify_plain_callback_t *callback)
 
141
{
 
142
        struct passdb_dict_request *dict_request;
 
143
 
 
144
        dict_request = p_new(request->pool, struct passdb_dict_request, 1);
 
145
        dict_request->auth_request = request;
 
146
        dict_request->callback.verify_plain = callback;
 
147
 
 
148
        passdb_dict_lookup_pass(dict_request);
 
149
}
 
150
 
 
151
static void dict_lookup_credentials(struct auth_request *request,
 
152
                                    lookup_credentials_callback_t *callback)
 
153
{
 
154
        struct passdb_dict_request *dict_request;
 
155
 
 
156
        dict_request = p_new(request->pool, struct passdb_dict_request, 1);
 
157
        dict_request->auth_request = request;
 
158
        dict_request->callback.lookup_credentials = callback;
 
159
 
 
160
        passdb_dict_lookup_pass(dict_request);
 
161
}
 
162
 
 
163
static struct passdb_module *
 
164
passdb_dict_preinit(pool_t pool, const char *args)
 
165
{
 
166
        struct dict_passdb_module *module;
 
167
        struct dict_connection *conn;
 
168
 
 
169
        module = p_new(pool, struct dict_passdb_module, 1);
 
170
        module->conn = conn = db_dict_init(args);
 
171
 
 
172
        module->module.blocking = TRUE;
 
173
        module->module.cache_key =
 
174
                auth_cache_parse_key(pool, conn->set.password_key);
 
175
        module->module.default_pass_scheme = conn->set.default_pass_scheme;
 
176
        return &module->module;
 
177
}
 
178
 
 
179
static void passdb_dict_deinit(struct passdb_module *_module)
 
180
{
 
181
        struct dict_passdb_module *module =
 
182
                (struct dict_passdb_module *)_module;
 
183
 
 
184
        db_dict_unref(&module->conn);
 
185
}
 
186
 
 
187
struct passdb_module_interface passdb_dict = {
 
188
        "dict",
 
189
 
 
190
        passdb_dict_preinit,
 
191
        NULL,
 
192
        passdb_dict_deinit,
 
193
       
 
194
        dict_verify_plain,
 
195
        dict_lookup_credentials,
 
196
        NULL
 
197
};