+static APR_OPTIONAL_FN_TYPE(ssl_is_https) *mag_is_https = NULL;
+
+static int mag_post_config(apr_pool_t *cfgpool, apr_pool_t *log,
+ apr_pool_t *temp, server_rec *s)
+{
+ /* FIXME: create mutex to deal with connections and contexts ? */
+ mag_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
+ mag_post_config_session();
+ ap_add_version_component(cfgpool, MOD_AUTH_GSSAPI_VERSION);
+
+ return OK;
+}
+
+static int mag_pre_connection(conn_rec *c, void *csd)
+{
+ struct mag_conn *mc;
+
+ mc = apr_pcalloc(c->pool, sizeof(struct mag_conn));
+
+ mc->parent = c->pool;
+ ap_set_module_config(c->conn_config, &auth_gssapi_module, (void*)mc);
+ return OK;
+}
+
+static apr_status_t mag_conn_destroy(void *ptr)
+{
+ struct mag_conn *mc = (struct mag_conn *)ptr;
+ uint32_t min;
+
+ if (mc->ctx) {
+ (void)gss_delete_sec_context(&min, &mc->ctx, GSS_C_NO_BUFFER);
+ mc->established = false;
+ }
+ return APR_SUCCESS;
+}
+
+static bool mag_conn_is_https(conn_rec *c)
+{
+ if (mag_is_https) {
+ if (mag_is_https(c)) return true;
+ }
+
+ return false;
+}
+
+#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 void mag_store_deleg_creds(request_rec *req,
+ char *dir, char *clientname,
+ gss_cred_id_t delegated_cred,
+ char **ccachefile)
+{
+ gss_key_value_element_desc element;
+ gss_key_value_set_desc store;
+ char *value;
+ uint32_t maj, min;
+ 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, clientname, '~', "~~");
+ if (!escaped) return;
+ /* then escape away the separator (/) if any */
+ escaped = escape(req->pool, escaped, '/', "~");
+ if (!escaped) return;
+
+ value = apr_psprintf(req->pool, "FILE:%s/%s", dir, escaped);
+
+ element.key = "ccache";
+ element.value = value;
+ store.elements = &element;
+ store.count = 1;
+
+ maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
+ GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
+ if (GSS_ERROR(maj)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s",
+ mag_error(req, "failed to store delegated creds",
+ maj, min));
+ }
+
+ *ccachefile = value;
+}
+#endif
+