~ubuntu-branches/ubuntu/vivid/dovecot/vivid

« back to all changes in this revision

Viewing changes to src/auth/auth.c

  • Committer: Bazaar Package Importer
  • Author(s): Jaldhar H. Vyas
  • Date: 2005-11-05 23:19:19 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20051105231919-ydujs4y7687fpor2
Tags: upstream-1.0.alpha4
ImportĀ upstreamĀ versionĀ 1.0.alpha4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2005 Timo Sirainen */
 
2
 
 
3
#include "common.h"
 
4
#include "network.h"
 
5
#include "buffer.h"
 
6
#include "str.h"
 
7
#include "mech.h"
 
8
#include "userdb.h"
 
9
#include "passdb.h"
 
10
#include "passdb-cache.h"
 
11
#include "auth.h"
 
12
#include "auth-request-handler.h"
 
13
 
 
14
#include <stdlib.h>
 
15
#include <unistd.h>
 
16
 
 
17
struct auth *auth_preinit(void)
 
18
{
 
19
        struct auth *auth;
 
20
        struct auth_passdb *auth_passdb;
 
21
        const char *driver, *args;
 
22
        pool_t pool;
 
23
        unsigned int i;
 
24
 
 
25
        pool = pool_alloconly_create("auth", 2048);
 
26
        auth = p_new(pool, struct auth, 1);
 
27
        auth->pool = pool;
 
28
 
 
29
        auth->verbose = getenv("VERBOSE") != NULL;
 
30
        auth->verbose_debug = getenv("VERBOSE_DEBUG") != NULL;
 
31
 
 
32
        t_push();
 
33
        for (i = 1; ; i++) {
 
34
                driver = getenv(t_strdup_printf("PASSDB_%u_DRIVER", i));
 
35
                if (driver == NULL)
 
36
                        break;
 
37
 
 
38
                args = getenv(t_strdup_printf("PASSDB_%u_ARGS", i));
 
39
                auth_passdb = passdb_preinit(auth, driver, args);
 
40
 
 
41
                if (getenv(t_strdup_printf("PASSDB_%u_DENY", i)) != NULL)
 
42
                        auth_passdb->deny = TRUE;
 
43
 
 
44
        }
 
45
        t_pop();
 
46
 
 
47
        t_push();
 
48
        for (i = 1; ; i++) {
 
49
                driver = getenv(t_strdup_printf("USERDB_%u_DRIVER", i));
 
50
                if (driver == NULL)
 
51
                        break;
 
52
 
 
53
                args = getenv(t_strdup_printf("USERDB_%u_ARGS", i));
 
54
                userdb_preinit(auth, driver, args);
 
55
 
 
56
        }
 
57
        t_pop();
 
58
 
 
59
        if (auth->passdbs == NULL)
 
60
                i_fatal("No password databases set");
 
61
        if (auth->userdbs == NULL)
 
62
                i_fatal("No user databases set");
 
63
        return auth;
 
64
}
 
65
 
 
66
const string_t *auth_mechanisms_get_list(struct auth *auth)
 
67
{
 
68
        struct mech_module_list *list;
 
69
        string_t *str;
 
70
 
 
71
        str = t_str_new(128);
 
72
        for (list = auth->mech_modules; list != NULL; list = list->next)
 
73
                str_append(str, list->module.mech_name);
 
74
 
 
75
        return str;
 
76
}
 
77
 
 
78
static void auth_mech_register(struct auth *auth, struct mech_module *mech)
 
79
{
 
80
        struct mech_module_list *list;
 
81
 
 
82
        list = p_new(auth->pool, struct mech_module_list, 1);
 
83
        list->module = *mech;
 
84
 
 
85
        str_printfa(auth->mech_handshake, "MECH\t%s", mech->mech_name);
 
86
        if ((mech->flags & MECH_SEC_PRIVATE) != 0)
 
87
                str_append(auth->mech_handshake, "\tprivate");
 
88
        if ((mech->flags & MECH_SEC_ANONYMOUS) != 0)
 
89
                str_append(auth->mech_handshake, "\tanonymous");
 
90
        if ((mech->flags & MECH_SEC_PLAINTEXT) != 0)
 
91
                str_append(auth->mech_handshake, "\tplaintext");
 
92
        if ((mech->flags & MECH_SEC_DICTIONARY) != 0)
 
93
                str_append(auth->mech_handshake, "\tdictionary");
 
94
        if ((mech->flags & MECH_SEC_ACTIVE) != 0)
 
95
                str_append(auth->mech_handshake, "\tactive");
 
96
        if ((mech->flags & MECH_SEC_FORWARD_SECRECY) != 0)
 
97
                str_append(auth->mech_handshake, "\tforward-secrecy");
 
98
        if ((mech->flags & MECH_SEC_MUTUAL_AUTH) != 0)
 
99
                str_append(auth->mech_handshake, "\tmutual-auth");
 
100
        str_append_c(auth->mech_handshake, '\n');
 
101
 
 
102
        list->next = auth->mech_modules;
 
103
        auth->mech_modules = list;
 
104
}
 
105
 
 
106
static int auth_passdb_list_have_plain(struct auth *auth)
 
107
{
 
108
        struct auth_passdb *passdb;
 
109
 
 
110
        for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next) {
 
111
                if (passdb->passdb->iface->verify_plain != NULL)
 
112
                        return TRUE;
 
113
        }
 
114
        return FALSE;
 
115
}
 
116
 
 
117
static int auth_passdb_list_have_credentials(struct auth *auth)
 
118
{
 
119
        struct auth_passdb *passdb;
 
120
 
 
121
        for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next) {
 
122
                if (passdb->passdb->iface->lookup_credentials != NULL)
 
123
                        return TRUE;
 
124
        }
 
125
        return FALSE;
 
126
}
 
127
 
 
128
static void auth_mech_list_verify_passdb(struct auth *auth)
 
129
{
 
130
        struct mech_module_list *list;
 
131
 
 
132
        for (list = auth->mech_modules; list != NULL; list = list->next) {
 
133
                if (list->module.passdb_need_plain &&
 
134
                    !auth_passdb_list_have_plain(auth))
 
135
                        break;
 
136
                if (list->module.passdb_need_credentials &&
 
137
                    !auth_passdb_list_have_credentials(auth))
 
138
                        break;
 
139
        }
 
140
 
 
141
        if (list != NULL) {
 
142
                i_fatal("%s mechanism can't be supported with given passdbs",
 
143
                        list->module.mech_name);
 
144
        }
 
145
}
 
146
 
 
147
void auth_init(struct auth *auth)
 
148
{
 
149
        struct auth_passdb *passdb;
 
150
        struct auth_userdb *userdb;
 
151
        struct mech_module *mech;
 
152
        const char *const *mechanisms;
 
153
        const char *env;
 
154
 
 
155
        for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next)
 
156
                passdb_init(passdb);
 
157
        for (userdb = auth->userdbs; userdb != NULL; userdb = userdb->next)
 
158
                userdb_init(userdb);
 
159
        passdb_cache_init();
 
160
 
 
161
        auth->mech_handshake = str_new(auth->pool, 512);
 
162
 
 
163
        auth->anonymous_username = getenv("ANONYMOUS_USERNAME");
 
164
        if (auth->anonymous_username != NULL &&
 
165
            *auth->anonymous_username == '\0')
 
166
                auth->anonymous_username = NULL;
 
167
 
 
168
        /* register wanted mechanisms */
 
169
        env = getenv("MECHANISMS");
 
170
        if (env == NULL)
 
171
                i_fatal("MECHANISMS environment is unset");
 
172
 
 
173
        mechanisms = t_strsplit_spaces(env, " ");
 
174
        while (*mechanisms != NULL) {
 
175
                if (strcasecmp(*mechanisms, "ANONYMOUS") == 0) {
 
176
                        if (auth->anonymous_username == NULL) {
 
177
                                i_fatal("ANONYMOUS listed in mechanisms, "
 
178
                                        "but anonymous_username not given");
 
179
                        }
 
180
                }
 
181
                mech = mech_module_find(*mechanisms);
 
182
                if (mech == NULL) {
 
183
                        i_fatal("Unknown authentication mechanism '%s'",
 
184
                                *mechanisms);
 
185
                }
 
186
                auth_mech_register(auth, mech);
 
187
 
 
188
                mechanisms++;
 
189
        }
 
190
 
 
191
        if (auth->mech_modules == NULL)
 
192
                i_fatal("No authentication mechanisms configured");
 
193
        auth_mech_list_verify_passdb(auth);
 
194
 
 
195
        /* get our realm - note that we allocate from data stack so
 
196
           this function should never be called inside I/O loop or anywhere
 
197
           else where t_pop() is called */
 
198
        env = getenv("REALMS");
 
199
        if (env == NULL)
 
200
                env = "";
 
201
        auth->auth_realms = t_strsplit_spaces(env, " ");
 
202
 
 
203
        auth->default_realm = getenv("DEFAULT_REALM");
 
204
        if (auth->default_realm != NULL && *auth->default_realm == '\0')
 
205
                auth->default_realm = NULL;
 
206
 
 
207
        env = getenv("USERNAME_CHARS");
 
208
        if (env == NULL || *env == '\0') {
 
209
                /* all chars are allowed */
 
210
                memset(auth->username_chars, 1, sizeof(auth->username_chars));
 
211
        } else {
 
212
                for (; *env != '\0'; env++)
 
213
                        auth->username_chars[(int)(uint8_t)*env] = 1;
 
214
        }
 
215
 
 
216
        env = getenv("USERNAME_TRANSLATION");
 
217
        if (env != NULL) {
 
218
                for (; *env != '\0' && env[1] != '\0'; env += 2)
 
219
                        auth->username_translation[(int)(uint8_t)*env] = env[1];
 
220
        }
 
221
 
 
222
        auth->ssl_require_client_cert =
 
223
                getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
 
224
        auth->ssl_username_from_cert =
 
225
                getenv("SSL_USERNAME_FROM_CERT") != NULL;
 
226
}
 
227
 
 
228
void auth_deinit(struct auth *auth)
 
229
{
 
230
        struct auth_passdb *passdb;
 
231
        struct auth_userdb *userdb;
 
232
 
 
233
        passdb_cache_deinit();
 
234
        for (passdb = auth->passdbs; passdb != NULL; passdb = passdb->next)
 
235
                passdb_deinit(passdb);
 
236
        for (userdb = auth->userdbs; userdb != NULL; userdb = userdb->next)
 
237
                userdb_deinit(userdb);
 
238
 
 
239
        pool_unref(auth->pool);
 
240
}