mech.c revision 63f168d7a6f67842872ebef8d1d3aec3d6b23939
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainenconst char *const *auth_realms;
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainenchar username_chars[256], username_translation[256];
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainenvoid mech_register_module(struct mech_module *module)
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen str_printfa(mech_handshake, "MECH\t%s", module->mech_name);
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen if ((module->flags & MECH_SEC_ANONYMOUS) != 0)
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen if ((module->flags & MECH_SEC_PLAINTEXT) != 0)
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen if ((module->flags & MECH_SEC_DICTIONARY) != 0)
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen if ((module->flags & MECH_SEC_FORWARD_SECRECY) != 0)
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen str_append(mech_handshake, "\tforward-secrecy");
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainen if ((module->flags & MECH_SEC_MUTUAL_AUTH) != 0)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid mech_unregister_module(struct mech_module *module)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen for (pos = &mech_modules; *pos != NULL; pos = &(*pos)->next) {
baebb412a9a5a44b1756e01cfa3b99f5d8a846b6Timo Sirainen if (strcmp((*pos)->module.mech_name, module->mech_name) == 0) {
12c6ef6f1268ed4d5b63709bb4215c481b4f078cTimo Sirainen for (list = mech_modules; list != NULL; list = list->next)
12c6ef6f1268ed4d5b63709bb4215c481b4f078cTimo Sirainenstruct mech_module *mech_module_find(const char *name)
12c6ef6f1268ed4d5b63709bb4215c481b4f078cTimo Sirainen for (list = mech_modules; list != NULL; list = list->next) {
12c6ef6f1268ed4d5b63709bb4215c481b4f078cTimo Sirainen if (strcasecmp(list->module.mech_name, name) == 0)
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainenstruct auth_request *auth_request_new(struct mech_module *mech)
46ec792dd4ccf6c34706c4774228301fafde6aa9Timo Sirainenvoid auth_request_destroy(struct auth_request *request)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid mech_auth_finish(struct auth_request *request,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const void *data, size_t data_size, int success)
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen /* passdb specifically requested to to delay the
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen request->callback(request, AUTH_CLIENT_RESULT_FAILURE,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* failure. don't announce it immediately to avoid
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen a) timing attacks, b) flooding */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen requests += auth_failures_buf->used/sizeof(*requests)-1;
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen buffer_append(auth_failures_buf, &request, sizeof(request));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* make sure the request isn't found anymore */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (request->no_login || request->conn == NULL ||
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen AUTH_MASTER_IS_DUMMY(request->conn->master)) {
54533aa265f5c87730022cc7576090bc51370f97Timo Sirainen /* we don't have master process, the request is no longer
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint mech_fix_username(char *username, const char **error_r)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen unsigned char *p;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* Some PAM plugins go nuts with empty usernames */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (p = (unsigned char *)username; *p != '\0'; p++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *error_r = "Username contains disallowed characters";
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenvoid auth_request_ref(struct auth_request *request)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenint auth_request_unref(struct auth_request *request)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenauth_request_extra_begin(struct auth_request *request,
2aac7ca853f63b62ea79ef8eae9ded83ed6063a5Timo Sirainen extra->user_password = i_strdup(user_password);
54533aa265f5c87730022cc7576090bc51370f97Timo Sirainenvoid auth_request_extra_next(struct auth_request_extra *extra,
bdb9f7f7fbf828fb85a393bd2803167b1bb8ff0dTimo Sirainen /* don't delay replying to client of the failure */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen extra->str = str = str_new(extra->request->pool, 64);
ec23e16ed879e289d12c6e1a5f9745dd3979004aTimo Sirainen /* user can't actually login - don't keep this
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen reply for master */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* we're proxying authentication for this user. send
ec23e16ed879e289d12c6e1a5f9745dd3979004aTimo Sirainen password back if using plaintext authentication. */
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainenvoid auth_request_extra_finish(struct auth_request_extra *extra,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen if (passdb_cache != NULL && cache_key != NULL) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen auth_cache_insert(passdb_cache, extra->request, cache_key,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* we're proxying - send back the password that was
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen sent by user (not the password in passdb). */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen extra->request->extra_fields = str_c(extra->str);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen safe_memset(extra->password, 0, strlen(extra->password));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *escape_none(const char *str)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenauth_request_get_var_expand_table(const struct auth_request *auth_request,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *(*escape_func)(const char *))
717bb0dbaf4bd3f745669570647845e6d493bfe0Timo Sirainen static struct var_expand_table static_tab[] = {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[0].value = escape_func(auth_request->user);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen tab[1].value = escape_func(t_strcut(auth_request->user, '@'));
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[2].value = strchr(auth_request->user, '@');
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* tab[4] = we have no home dir */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[5].value = net_ip2addr(&auth_request->local_ip);
54533aa265f5c87730022cc7576090bc51370f97Timo Sirainen tab[6].value = net_ip2addr(&auth_request->remote_ip);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen tab[7].value = dec2str(auth_request->conn->pid);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenconst char *get_log_prefix(const struct auth_request *auth_request)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *ip;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (i = 0; i < size; i++) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void auth_failure_timeout(void *context __attr_unused__)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void mech_list_verify_passdb(struct passdb_module *passdb)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen for (list = mech_modules; list != NULL; list = list->next) {
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen i_fatal("Passdb %s doesn't support %s method",
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen const char *const *mechanisms;
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen const char *env;
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen anonymous_username = getenv("ANONYMOUS_USERNAME");
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen if (anonymous_username != NULL && *anonymous_username == '\0')
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen /* register wanted mechanisms */
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "LOGIN") == 0)
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "APOP") == 0)
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "CRAM-MD5") == 0)
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "DIGEST-MD5") == 0)
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "NTLM") == 0)
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen else if (strcasecmp(*mechanisms, "ANONYMOUS") == 0) {
b5917cf6476ffb7cdeb2e2544057ea1605ea6fdcTimo Sirainen "but anonymous_username not given");
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen i_fatal("Unknown authentication mechanism '%s'",
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen i_fatal("No authentication mechanisms configured");
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen /* get our realm - note that we allocate from data stack so
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen this function should never be called inside I/O loop or anywhere
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen else where t_pop() is called */
9439bed2f07d6475febd8a247cd2f0990fb32a13Timo Sirainen if (default_realm != NULL && *default_realm == '\0')
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen /* all chars are allowed */
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen memset(username_chars, 1, sizeof(username_chars));
12cf3d0e03fc70fb0c8b91bc8fd83b4e14d7cdefTimo Sirainen memset(username_chars, 0, sizeof(username_chars));
4ead43ecc06d10047998966c4dc0b142ecce4b66Timo Sirainen username_chars[((unsigned char)*env) & 0xff] = 1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen memset(username_translation, 0, sizeof(username_translation));
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen for (; *env != '\0' && env[1] != '\0'; env += 2) {
bb8d0ec26bdd548624d7a7424071cca693b72f55Timo Sirainen username_translation[((unsigned char)*env) & 0xff] =
506e41a4efbc7f4bba93cd295ca4dba18ed3cf09Timo Sirainen ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
b55f914c0ade77252cfd798ea8eb9a84bda56315Timo Sirainen auth_failures_buf = buffer_create_dynamic(default_pool, 1024);