struct mechanisms_register * mech_register_init(const struct auth_settings *set) { struct mechanisms_register *reg; const struct mech_module *mech; const char *const *mechanisms; pool_t pool; pool = pool_alloconly_create("mechanisms register", 1024); reg = p_new(pool, struct mechanisms_register, 1); reg->pool = pool; reg->set = set; reg->handshake = str_new(pool, 512); mechanisms = t_strsplit_spaces(set->mechanisms, " "); for (; *mechanisms != NULL; mechanisms++) { const char *name = *mechanisms; if (strcasecmp(name, "ANONYMOUS") == 0) { if (*set->anonymous_username == '\0') { i_fatal("ANONYMOUS listed in mechanisms, " "but anonymous_username not set"); } } mech = mech_module_find(name); if (mech == NULL) { /* maybe it's a plugin. try to load it. */ auth_module_load(mech_get_plugin_name(name)); mech = mech_module_find(name); } if (mech == NULL) i_fatal("Unknown authentication mechanism '%s'", name); mech_register_add(reg, mech); } if (reg->modules == NULL) i_fatal("No authentication mechanisms configured"); return reg; }
bool auth_request_handler_auth_begin(struct auth_request_handler *handler, const char *args) { const struct mech_module *mech; struct auth_request *request; const char *const *list, *name, *arg, *initial_resp; void *initial_resp_data; unsigned int id; buffer_t *buf; i_assert(!handler->destroyed); /* <id> <mechanism> [...] */ list = t_strsplit_tab(args); if (list[0] == NULL || list[1] == NULL || str_to_uint(list[0], &id) < 0) { i_error("BUG: Authentication client %u " "sent broken AUTH request", handler->client_pid); return FALSE; } if (handler->token_auth) { mech = &mech_dovecot_token; if (strcmp(list[1], mech->mech_name) != 0) { /* unsupported mechanism */ i_error("BUG: Authentication client %u requested invalid " "authentication mechanism %s (DOVECOT-TOKEN required)", handler->client_pid, str_sanitize(list[1], MAX_MECH_NAME_LEN)); return FALSE; } } else { mech = mech_module_find(list[1]); if (mech == NULL) { /* unsupported mechanism */ i_error("BUG: Authentication client %u requested unsupported " "authentication mechanism %s", handler->client_pid, str_sanitize(list[1], MAX_MECH_NAME_LEN)); return FALSE; } } request = auth_request_new(mech); request->handler = handler; request->connect_uid = handler->connect_uid; request->client_pid = handler->client_pid; request->id = id; request->auth_only = handler->master_callback == NULL; /* parse optional parameters */ initial_resp = NULL; for (list += 2; *list != NULL; list++) { arg = strchr(*list, '='); if (arg == NULL) { name = *list; arg = ""; } else { name = t_strdup_until(*list, arg); arg++; } if (auth_request_import_auth(request, name, arg)) ; else if (strcmp(name, "resp") == 0) { initial_resp = arg; /* this must be the last parameter */ list++; break; } } if (*list != NULL) { i_error("BUG: Authentication client %u " "sent AUTH parameters after 'resp'", handler->client_pid); auth_request_unref(&request); return FALSE; } if (request->service == NULL) { i_error("BUG: Authentication client %u " "didn't specify service in request", handler->client_pid); auth_request_unref(&request); return FALSE; } if (hash_table_lookup(handler->requests, POINTER_CAST(id)) != NULL) { i_error("BUG: Authentication client %u " "sent a duplicate ID %u", handler->client_pid, id); auth_request_unref(&request); return FALSE; } auth_request_init(request); request->to_abort = timeout_add(MASTER_AUTH_SERVER_TIMEOUT_SECS * 1000, auth_request_timeout, request); hash_table_insert(handler->requests, POINTER_CAST(id), request); if (request->set->ssl_require_client_cert && !request->valid_client_cert) { /* we fail without valid certificate */ auth_request_handler_auth_fail(handler, request, "Client didn't present valid SSL certificate"); return TRUE; } /* Empty initial response is a "=" base64 string. Completely empty string shouldn't really be sent, but at least Exim does it, so just allow it for backwards compatibility.. */ if (initial_resp != NULL && *initial_resp != '\0') { size_t len = strlen(initial_resp); buf = buffer_create_dynamic(pool_datastack_create(), MAX_BASE64_DECODED_SIZE(len)); if (base64_decode(initial_resp, len, NULL, buf) < 0) { auth_request_handler_auth_fail(handler, request, "Invalid base64 data in initial response"); return TRUE; } initial_resp_data = p_malloc(request->pool, I_MAX(buf->used, 1)); memcpy(initial_resp_data, buf->data, buf->used); request->initial_response = initial_resp_data; request->initial_response_len = buf->used; } /* handler is referenced until auth_request_handler_reply() is called. */ handler->refcount++; /* before we start authenticating, see if we need to wait first */ auth_penalty_lookup(auth_penalty, request, auth_penalty_callback); return TRUE; }