db-passwd-file.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen#if defined (USERDB_PASSWD_FILE) || defined(PASSDB_PASSWD_FILE)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic void passwd_file_add(struct passwd_file *pw, const char *username,
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* args = uid, gid, user info, home dir, shell, extra_fields */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (hash_lookup(pw->users, username) != NULL) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: User %s exists more than once",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (len > 4 && pass[0] != '{' && pass[0] != '$' &&
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* password[type] - we're being libpam-pwdfile compatible
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen here. it uses 13 = DES and 34 = MD5. For backwards
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen comaptibility with ourself, we have also 56 = Digest-MD5. */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen int num = (pass[len-3] - '0') * 10 + (pass[len-2] - '0');
12f0c4396d2d9c02b7d5e070aaf64fed5853e9bfAki Tuomi pu->password = p_strconcat(pw->pool, "{PLAIN-MD5}",
12f0c4396d2d9c02b7d5e070aaf64fed5853e9bfAki Tuomi pu->password = p_strconcat(pw->pool, "{DIGEST-MD5}",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen "has invalid password",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen pu->password = p_strconcat(pw->pool, "{CRYPT}",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: User %s has invalid UID '%s'",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: User %s has invalid GID '%s'",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* user info */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* old format, this field is empty and next field may
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen contain MAIL */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (*args != NULL && **args != '\0' && pw->db->userdb) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* new format, contains a space separated list of
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen extra fields */
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen p_strsplit_spaces(pw->pool, extra_fields, " ");
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic struct passwd_file *
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenpasswd_file_new(struct db_passwd_file *db, const char *expanded_path)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic bool passwd_file_open(struct passwd_file *pw)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: Can't open file: %m", pw->path);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: fstat() failed: %m", pw->path);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen pw->pool = pool_alloconly_create("passwd_file", 10240);;
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen pw->users = hash_create(default_pool, pw->pool, 100,
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen input = i_stream_create_fd(pw->fd, 4096, FALSE);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen while ((line = i_stream_read_next_line(input)) != NULL) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (*line == '\0' || *line == ':' || *line == '#')
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen continue; /* no username or comment */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen const char *const *args = t_strsplit(line, ":");
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* at least username+password */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen passwd_file_add(pw, args[0], args[1], args+2);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* only username */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic void passwd_file_close(struct passwd_file *pw)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: close() failed: %m", pw->path);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic void passwd_file_free(struct passwd_file *pw)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic bool passwd_file_sync(struct passwd_file *pw)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* with variables don't give hard errors, or errors about
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen nonexisting files */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen i_error("passwd-file %s: stat() failed: %m", pw->path);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (st.st_mtime != pw->stamp || st.st_size != pw->size) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic struct db_passwd_file *db_passwd_file_find(const char *path)
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen for (f = passwd_files; f != NULL; f = f->next) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainendb_passwd_file_init(const char *path, const char *username_format,
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen const char *p;
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* just extra escaped % chars. remove them. */
45b0d8d0b97be14d10e3a3c12c169e4b352b2aacTimo Sirainen db->files = hash_create(default_pool, default_pool, 100,
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenvoid db_passwd_file_parse(struct db_passwd_file *db)
48325adac125d7ff275ec69b05b7a92be9637630Timo Sirainen if (db->default_file != NULL && db->default_file->stamp == 0) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* no variables, open the file immediately */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenvoid db_passwd_file_unref(struct db_passwd_file **_db)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen for (p = &passwd_files; *p != NULL; p = &(*p)->next) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen if (*p == db) {
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainenstatic const char *
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen const struct auth_request *auth_request ATTR_UNUSED)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen const char *p;
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen /* most likely this is an invalid request. just cut off the '/' and
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen everything after it. */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainendb_passwd_file_lookup(struct db_passwd_file *db, struct auth_request *request)
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen table = auth_request_get_var_expand_table(request, path_fix);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen /* doesn't exist yet. create lookup for it. */
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen /* pw may be freed now */
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen table = auth_request_get_var_expand_table(request,
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen var_expand(username, db->username_format, table);
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen auth_request_log_debug(request, "passwd-file",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen "lookup: user=%s file=%s",
7a896d960824c93e2f04ac21e8eae0f892bf8d20Timo Sirainen auth_request_log_info(request, "passwd-file", "unknown user");