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