Coverage Report

Created: 2026-11-12 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mod_auth_openidc/src/util/request_state.c
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
/***************************************************************************
21
 * Copyright (C) 2017-2026 ZmartZone Holding BV
22
 * All rights reserved.
23
 *
24
 * DISCLAIMER OF WARRANTIES:
25
 *
26
 * THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
27
 * ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
28
 * WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
29
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  NOR ARE THERE ANY
30
 * WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
31
 * USAGE.  FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
32
 * YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
33
 * WILL BE UNINTERRUPTED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
34
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
36
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
 *
40
 * @Author: Hans Zandbelt - hans.zandbelt@openidc.com
41
 */
42
43
/*
44
 * per-request state store: a hash table hung off the (main) request's pool userdata, used to pass
45
 * state between the Apache request-processing stages and hook callbacks.
46
 *
47
 * This is a plain utility over request_rec and carries no mod_auth_openidc configuration or
48
 * protocol knowledge, which is why it lives here rather than in the module core: util/util.c and
49
 * util/html.c needed exactly these symbols and had to include mod_auth_openidc.h to get them.
50
 */
51
52
#include "util/request_state.h"
53
54
#include "json.h"
55
56
#include <apr_hash.h>
57
#include <apr_strings.h>
58
59
/* the key under which the state hash is stored in the request pool's userdata */
60
11.5k
#define OIDC_USERDATA_KEY "mod_auth_openidc_state"
61
/*
62
 * get the mod_auth_openidc related context from the (userdata in the) request
63
 * (used for passing state between various Apache request processing stages and hook callbacks)
64
 */
65
7.68k
static apr_hash_t *oidc_request_state(request_rec *rr) {
66
67
  /* our state is always stored in the main request */
68
7.68k
  request_rec *r = (rr->main != NULL) ? rr->main : rr;
69
70
  /* our state is a hash table, get it */
71
7.68k
  apr_hash_t *state = NULL;
72
7.68k
  apr_pool_userdata_get((void **)&state, OIDC_USERDATA_KEY, r->pool);
73
74
  /* if it does not exist, we'll create a new hash table */
75
7.68k
  if (state == NULL) {
76
3.87k
    state = apr_hash_make(r->pool);
77
3.87k
    apr_pool_userdata_set(state, OIDC_USERDATA_KEY, NULL, r->pool);
78
3.87k
  }
79
80
  /* return the resulting table, always non-null now */
81
7.68k
  return state;
82
7.68k
}
83
84
/*
85
 * set a name/value pair in the mod_auth_openidc-specific request context
86
 * (used for passing state between various Apache request processing stages and hook callbacks)
87
 */
88
6.40k
void oidc_request_state_set(request_rec *r, const char *key, const char *value) {
89
90
  /* get a handle to the global state, which is a hash table */
91
6.40k
  apr_hash_t *state = oidc_request_state(r);
92
93
  /* put the name/value pair in that hash table */
94
6.40k
  apr_hash_set(state, key, APR_HASH_KEY_STRING, value);
95
6.40k
}
96
97
/*
98
 * get a name/value pair from the mod_auth_openidc-specific request context
99
 * (used for passing state between various Apache request processing stages and hook callbacks)
100
 */
101
386
const char *oidc_request_state_get(request_rec *r, const char *key) {
102
103
  /* get a handle to the global state, which is a hash table */
104
386
  apr_hash_t *state = oidc_request_state(r);
105
106
  /* return the value from the hash table */
107
386
  return (const char *)apr_hash_get(state, key, APR_HASH_KEY_STRING);
108
386
}
109
110
/*
111
 * get a name/json object pair from the mod_auth_openidc-specific request context
112
 * (used for passing state between various Apache request processing stages and hook callbacks)
113
 */
114
0
oidc_json_t *oidc_request_state_json_get(request_rec *r, const char *key) {
115
116
  /* get a handle to the global state, which is a hash table */
117
0
  apr_hash_t *state = oidc_request_state(r);
118
119
  /* return the value from the hash table */
120
0
  return (oidc_json_t *)apr_hash_get(state, key, APR_HASH_KEY_STRING);
121
0
}
122
123
/*
124
 * APR pool cleanup callback that releases a request-state JSON object
125
 */
126
897
static apr_status_t oidc_request_state_json_cleanup(void *json) {
127
897
  oidc_json_decref((oidc_json_t *)json);
128
897
  return APR_SUCCESS;
129
897
}
130
131
/*
132
 * set a name/json object pair in the mod_auth_openidc-specific request context, taking over
133
 * ownership of (i.e. "stealing", jansson-style "_new" semantics) the provided reference
134
 * (used for passing state between various Apache request processing stages and hook callbacks)
135
 */
136
897
void oidc_request_state_json_set_new(request_rec *r, const char *key, oidc_json_t *value) {
137
138
  /* get a handle to the global state, which is a hash table */
139
897
  apr_hash_t *state = oidc_request_state(r);
140
141
  /* register a cleanup for the json object on the pool of the (main) request that owns the
142
   * state hash: a subrequest pool would be destroyed while the state may still be in use */
143
897
  request_rec *main_r = (r->main != NULL) ? r->main : r;
144
897
  apr_pool_cleanup_register(main_r->pool, value, oidc_request_state_json_cleanup, apr_pool_cleanup_null);
145
146
  /* put the name/value pair in that hash table */
147
897
  apr_hash_set(state, key, APR_HASH_KEY_STRING, value);
148
897
}
149
150
/*
151
 * set a name/json object pair in the mod_auth_openidc-specific request context
152
 * (used for passing state between various Apache request processing stages and hook callbacks)
153
 */
154
897
void oidc_request_state_json_set(request_rec *r, const char *key, const oidc_json_t *value) {
155
156
  /* make a copy of the json object because the session object in the caller will be cleared */
157
897
  oidc_request_state_json_set_new(r, key, oidc_json_copy(value));
158
897
}