bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch/* Auth process maintains a random secret. Once a user authenticates the
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch response to the REQUEST command from a master service is augmented with an
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_token value. This token is the SHA1 hash of the secret, the service
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch name and the username of the user that just logged in. Using this token the
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch service (e.g. imap) can login to another service (e.g. imap-urlauth) to
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch gain access to resources that require additional privileges (e.g. another
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch user's e-mail).
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch#define AUTH_TOKEN_SECRET_FNAME "auth-token-secret.dat"
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschstatic unsigned char auth_token_secret[AUTH_TOKEN_SECRET_LEN];
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch unsigned char secret_r[AUTH_TOKEN_SECRET_LEN])
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* check secret len and file type */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (st.st_size != AUTH_TOKEN_SECRET_LEN || !S_ISREG(st.st_mode)) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Corrupted token secret file: %s", path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* verify that we're not dealing with a symbolic link */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* check security parameters for compromise */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch !S_ISREG(lst.st_mode) || st.st_ino != lst.st_ino ||
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Compromised token secret file: %s", path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* FIXME: fail here to generate new secret if stored one is too old */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch ret = read_full(fd, secret_r, AUTH_TOKEN_SECRET_LEN);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch else if (ret == 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Token secret file unexpectedly shrank: %s", path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_debug("Read auth token secret from %s", path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const unsigned char secret[AUTH_TOKEN_SECRET_LEN])
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch fd = open(temp_path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch ret = write_full(fd, secret, AUTH_TOKEN_SECRET_LEN);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("rename(%s, %s) failed: %m", temp_path, path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_debug("Wrote new auth token secret to %s", path);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch t_strconcat(global_auth_settings->base_dir, "/",
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (auth_token_read_secret(secret_path, auth_token_secret) < 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch random_fill(auth_token_secret, sizeof(auth_token_secret));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (auth_token_write_secret(secret_path, auth_token_secret) < 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Failed to write auth token secret file; "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "returned tokens will be invalid once auth restarts");
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* not very useful, but we do it anyway */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch safe_memset(auth_token_secret, 0, sizeof(auth_token_secret));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschconst char *auth_token_get(const char *service, const char *session_pid,
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz hmac_init(&ctx, (const unsigned char*)username, strlen(username),
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz hmac_update(&ctx, session_pid, strlen(session_pid));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (session_id != NULL && *session_id != '\0')
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz hmac_update(&ctx, session_id, strlen(session_id));