+static bool mag_acquire_creds(request_rec *req,
+ struct mag_config *cfg,
+ gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *creds,
+ gss_OID_set *actual_mechs)
+{
+ uint32_t maj, min;
+#ifdef HAVE_CRED_STORE
+ gss_const_key_value_set_t store = cfg->cred_store;
+
+ maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
+ desired_mechs, cred_usage, store, creds,
+ actual_mechs, NULL);
+#else
+ maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
+ desired_mechs, cred_usage, creds,
+ actual_mechs, NULL);
+#endif
+
+ if (GSS_ERROR(maj)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
+ mag_error(req, "gss_acquire_cred[_from]() "
+ "failed to get server creds",
+ maj, min));
+ return false;
+ }
+
+ return true;
+}
+
+#ifdef HAVE_CRED_STORE
+static char *escape(apr_pool_t *pool, const char *name,
+ char find, const char *replace)
+{
+ char *escaped = NULL;
+ char *namecopy;
+ char *n;
+ char *p;
+
+ namecopy = apr_pstrdup(pool, name);
+
+ p = strchr(namecopy, find);
+ if (!p) return namecopy;
+
+ /* first segment */
+ n = namecopy;
+ while (p) {
+ /* terminate previous segment */
+ *p = '\0';
+ if (escaped) {
+ escaped = apr_pstrcat(pool, escaped, n, replace, NULL);
+ } else {
+ escaped = apr_pstrcat(pool, n, replace, NULL);
+ }
+ /* move to next segment */
+ n = p + 1;
+ p = strchr(n, find);
+ }
+ /* append last segment if any */
+ if (*n) {
+ escaped = apr_pstrcat(pool, escaped, n, NULL);
+ }
+
+ return escaped;
+}
+
+static char *mag_gss_name_to_ccache_name(request_rec *req,
+ char *dir, const char *gss_name)
+{
+ char *escaped;
+
+ /* We need to escape away '/', we can't have path separators in
+ * a ccache file name */
+ /* first double escape the esacping char (~) if any */
+ escaped = escape(req->pool, gss_name, '~', "~~");
+ /* then escape away the separator (/) if any */
+ escaped = escape(req->pool, escaped, '/', "~");
+
+ return apr_psprintf(req->pool, "%s/%s", dir, escaped);
+}
+
+static void mag_set_KRB5CCANME(request_rec *req, char *ccname)
+{
+ apr_status_t status;
+ apr_finfo_t finfo;
+ char *value;
+
+ status = apr_stat(&finfo, ccname, APR_FINFO_MIN, req->pool);
+ if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
+ /* set the file cache anyway, but warn */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
+ "KRB5CCNAME file (%s) lookup failed!", ccname);
+ }
+
+ value = apr_psprintf(req->pool, "FILE:%s", ccname);
+ apr_table_set(req->subprocess_env, "KRB5CCNAME", value);
+}
+