/** * Internal function to expand tokens in paths. * * Inputs: * * @context A krb5_context * @path_in The path to expand tokens from * * Outputs: * * @ppath_out Path with expanded tokens (caller must free() this) */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_path_tokens(krb5_context context, const char *path_in, char **ppath_out) { return _krb5_expand_path_tokensv(context, path_in, ppath_out, NULL); }
static krb5_error_code KRB5_LIB_CALL kuserok_user_k5login_plug_f(void *plug_ctx, krb5_context context, const char *rule, unsigned int flags, const char *k5login_dir, const char *luser, krb5_const_principal principal, krb5_boolean *result) { #ifdef _WIN32 return KRB5_PLUGIN_NO_HANDLE; #else char *path; char *path_exp; const char *profile_dir = NULL; krb5_error_code ret; krb5_boolean found_file = FALSE; struct passwd pw, *pwd = NULL; char pwbuf[2048]; if (strcmp(rule, "USER-K5LOGIN") != 0) return KRB5_PLUGIN_NO_HANDLE; profile_dir = k5login_dir; if (profile_dir == NULL) { /* Don't deadlock with gssd or anything of the sort */ if (!_krb5_homedir_access(context)) return KRB5_PLUGIN_NO_HANDLE; if (getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) { krb5_set_error_message(context, errno, "User unknown (getpwnam_r())"); return KRB5_PLUGIN_NO_HANDLE; } if (pwd == NULL) { krb5_set_error_message(context, errno, "User unknown (getpwnam())"); return KRB5_PLUGIN_NO_HANDLE; } profile_dir = pwd->pw_dir; } #define KLOGIN "/.k5login" if (asprintf(&path, "%s/.k5login.d", profile_dir) == -1) return krb5_enomem(context); ret = _krb5_expand_path_tokensv(context, path, 1, &path_exp, "luser", luser, NULL); free(path); if (ret) return ret; path = path_exp; /* check user's ~/.k5login */ path[strlen(path) - strlen(".d")] = '\0'; ret = check_one_file(context, path, luser, FALSE, principal, result); /* * A match in ~/.k5login is sufficient. A non-match, falls through to the * .k5login.d code below. */ if (ret == 0 && *result == TRUE) { free(path); return 0; } if (ret != ENOENT) found_file = TRUE; /* * A match in ~/.k5login.d/somefile is sufficient. A non-match, falls * through to the code below that handles negative results. * * XXX: put back the .d; clever|hackish? you decide */ path[strlen(path)] = '.'; ret = check_directory(context, path, luser, FALSE, principal, result); free(path); if (ret == 0 && *result == TRUE) return 0; if (ret != ENOENT && ret != ENOTDIR) found_file = TRUE; /* * When either ~/.k5login or ~/.k5login.d/ exists, but neither matches * and we're authoritative, we're done. Otherwise, give other plugins * a chance. */ *result = FALSE; if (found_file && (flags & KUSEROK_K5LOGIN_IS_AUTHORITATIVE)) return 0; return KRB5_PLUGIN_NO_HANDLE; #endif }