The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
auth.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 25ed29b8f5dde15c42efa35fda966d7f7912f4a6 $
19  *
20  * @file src/lib/server/auth.c
21  * @brief The old authentication state machine.
22  *
23  * @copyright 2000,2006 The FreeRADIUS server project
24  * @copyright 2000 Miquel van Smoorenburg (miquels@cistron.nl)
25  * @copyright 2000 Jeff Carneal (jeff@apex.net)
26  */
27 RCSID("$Id: 25ed29b8f5dde15c42efa35fda966d7f7912f4a6 $")
28 
29 #include <freeradius-devel/io/listen.h>
30 #include <freeradius-devel/server/base.h>
31 #include <freeradius-devel/server/module.h>
32 #include <freeradius-devel/server/rcode.h>
33 #include <freeradius-devel/server/state.h>
34 #include <freeradius-devel/unlang/call.h>
35 #include <freeradius-devel/util/debug.h>
36 
37 #include <freeradius-devel/util/print.h>
38 #include <freeradius-devel/radius/defs.h>
39 
40 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
41 
42 #include <ctype.h>
43 
44 /*
45  * Run a virtual server auth and postauth
46  *
47  */
49 {
50  RDEBUG("Virtual server %s received request NOT IMPLEMENTED", cf_section_name2(unlang_call_current(request)));
51  log_request_pair_list(L_DBG_LVL_1, request, NULL, &request->request_pairs, NULL);
52 
53  /*
54  * Just push the virtual server onto the stack?
55  *
56  * Except that the caller expects this function to be run
57  * _synchronously_, and all of that needs to be fixed.
58  */
60 
61 #if 0
62  {
63  fr_pair_t *username, *parent_username = NULL;
64  fr_pair_t *vp;
65 
66  username = fr_pair_find_by_num(&request->request_pairs, 0, FR_STRIPPED_USER_NAME);
67  if (!username) username = fr_pair_find_by_num(&request->request_pairs, 0, FR_USER_NAME);
68 
69  if (request->parent) {
70  parent_username = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_STRIPPED_USER_NAME);
71  if (!parent_username) parent_username = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_USER_NAME);
72  }
73 
74  /*
75  * Complain about possible issues related to tunnels.
76  */
77  if (username && parent_username) {
78  /*
79  * Look at the full User-Name with realm.
80  */
81  if (parent_username->da->attr == FR_STRIPPED_USER_NAME) {
82  vp = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_USER_NAME);
83  if (!vp) goto runit;
84  } else {
85  vp = parent_username;
86  }
87 
88  /*
89  * If the names aren't identical, we do some detailed checks.
90  */
91  if (strcmp(vp->vp_strvalue, username->vp_strvalue) != 0) {
92  char const *outer, *inner;
93 
94  outer = strchr(vp->vp_strvalue, '@');
95 
96  /*
97  * If there's no realm, or there's a user identifier before
98  * the realm name, check the user identifier.
99  *
100  * It SHOULD be "anonymous", or "anonymous@realm"
101  */
102  if (outer) {
103  if ((outer != vp->vp_strvalue) &&
104  ((vp->vp_length < 10) || (memcmp(vp->vp_strvalue, "anonymous@", 10) != 0))) {
105  RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
106  } /* else it is anonymized */
107 
108  /*
109  * Check when there's no realm, and without the trailing '@'
110  */
111  } else if ((vp->vp_length < 9) || (memcmp(vp->vp_strvalue, "anonymous", 9) != 0)) {
112  RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
113 
114  } /* else the user identifier is anonymized */
115 
116  /*
117  * Look for an inner realm, which may or may not exist.
118  */
119  inner = strchr(username->vp_strvalue, '@');
120  if (outer && inner) {
121  outer++;
122  inner++;
123 
124  /*
125  * The realms are different, do
126  * more detailed checks.
127  */
128  if (strcmp(outer, inner) != 0) {
129  size_t outer_len, inner_len;
130 
131  outer_len = vp->vp_length;
132  outer_len -= (outer - vp->vp_strvalue);
133 
134  inner_len = username->vp_length;
135  inner_len -= (inner - username->vp_strvalue);
136 
137  /*
138  * Inner: secure.example.org
139  * Outer: example.org
140  */
141  if (inner_len > outer_len) {
142  char const *suffix;
143 
144  suffix = inner + (inner_len - outer_len) - 1;
145 
146  if ((*suffix != '.') ||
147  (strcmp(suffix + 1, outer) != 0)) {
148  RWDEBUG("Possible spoofing: Inner realm '%s' is not a "
149  "subdomain of the outer realm '%s'", inner, outer);
150  }
151 
152  } else {
153  RWDEBUG("Possible spoofing: Inner realm and "
154  "outer realms are different");
155  }
156  }
157  }
158 
159  } else {
160  RWDEBUG("Outer and inner identities are the same. User privacy is compromised.");
161  }
162  }
163  }
164 
165  if (!request->async) {
166 #ifdef STATIC_ANALYZER
167  if (!request->parent) RETURN_MODULE_FAIL;
168 #endif
169  fr_assert(request->parent != NULL);
170 
171  request->async = talloc_memdup(request, request->parent->async, sizeof(fr_async_t));
172  talloc_set_name_const(request->async, talloc_get_name(request->parent->async));
173  }
174 
175  RDEBUG("server %s {", cf_section_name2(unlang_call_current(request)));
176  request->async->process(&final,
177  MODULE_CTX(dl_module_instance_by_data(request->async->process_inst), NULL, NULL, NULL),
178  request);
179  RDEBUG("} # server %s", cf_section_name2(unlang_call_current(request)));
180 
181  fr_cond_assert(final == RLM_MODULE_OK);
182 
183  if (!request->reply->code ||
184  (request->reply->code == FR_RADIUS_CODE_ACCESS_REJECT)) {
186  }
187 
188  if (request->reply->code == FR_RADIUS_CODE_ACCESS_CHALLENGE) {
190  }
191 
193 #endif
194 }
195 
196 /*
197  * Debug the packet if requested.
198  */
199 void common_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *pairs, bool received)
200 {
201 #ifdef WITH_IFINDEX_NAME_RESOLUTION
202  char if_name[IFNAMSIZ];
203 #endif
204 
205  if (!packet) return;
206  if (!RDEBUG_ENABLED) return;
207 
208 
209  log_request(L_DBG, L_DBG_LVL_1, request, __FILE__, __LINE__, "%s code %u Id %i from %s%pV%s:%i to %s%pV%s:%i "
210 #ifdef WITH_IFINDEX_NAME_RESOLUTION
211  "%s%s%s"
212 #endif
213  "length %zu",
214  received ? "Received" : "Sent",
215  packet->code,
216  packet->id,
217  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
218  fr_box_ipaddr(packet->socket.inet.src_ipaddr),
219  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
220  packet->socket.inet.src_port,
221  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
222  fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
223  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
224  packet->socket.inet.dst_port,
225 #ifdef WITH_IFINDEX_NAME_RESOLUTION
226  packet->socket.inet.ifindex ? "via " : "",
227  packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
228  packet->socket.inet.ifindex ? " " : "",
229 #endif
230  packet->data_len);
231 
232  if (received) {
233  log_request_pair_list(L_DBG_LVL_1, request, NULL, pairs, NULL);
234  } else {
235  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, pairs, NULL);
236  }
237 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
void common_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *pairs, bool received)
Definition: auth.c:199
unlang_action_t rad_virtual_server(rlm_rcode_t *p_result, request_t *request)
Definition: auth.c:48
#define RCSID(id)
Definition: build.h:444
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
Definition: call.c:225
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition: defs.h:35
dl_module_inst_t const * dl_module_instance_by_data(void const *data)
Lookup a dl_module_inst_t via instance data.
Definition: dl_module.c:215
Minimal data structure to use the new code.
Definition: listen.h:58
void log_request_proto_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a list of protocol fr_pair_ts.
Definition: log.c:845
void log_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt,...)
Marshal variadic log arguments into a va_list and pass to normal logging functions.
Definition: log.c:603
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition: log.c:821
#define RWDEBUG(fmt,...)
Definition: log.h:361
@ L_DBG_LVL_1
Highest priority debug messages (-x).
Definition: log.h:70
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
#define MODULE_CTX(_dl_inst, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
Definition: module_ctx.h:123
#define RDEBUG(fmt,...)
Definition: radclient.h:53
#define RDEBUG_ENABLED()
Definition: radclient.h:49
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_HANDLED
Definition: rcode.h:58
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
username
Definition: rlm_securid.c:420
RETURN_MODULE_FAIL
fr_assert(0)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
unsigned int code
Packet code (type).
Definition: packet.h:61
fr_socket_t socket
This packet was received on.
Definition: packet.h:57
int id
Packet ID (used to link requests/responses).
Definition: packet.h:60
size_t data_len
Length of packet data.
Definition: packet.h:64
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition: socket.h:78
#define fr_box_ipaddr(_val)
Definition: value.h:287