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: 53a8f7dfa8b94462a3c3cd38a5089f719feaece4 $
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: 53a8f7dfa8b94462a3c3cd38a5089f719feaece4 $")
28 
29 #include <freeradius-devel/io/listen.h>
30 #include <freeradius-devel/server/auth.h>
31 #include <freeradius-devel/server/module.h>
32 #include <freeradius-devel/server/protocol.h>
33 #include <freeradius-devel/server/rcode.h>
34 #include <freeradius-devel/server/state.h>
35 #include <freeradius-devel/unlang/call.h>
36 #include <freeradius-devel/util/debug.h>
37 
38 #include <freeradius-devel/util/print.h>
39 #include <freeradius-devel/radius/defs.h>
40 
41 #include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
42 
43 /*
44  * Run a virtual server auth and postauth
45  *
46  */
48 {
49  RDEBUG("Virtual server %s received request NOT IMPLEMENTED", cf_section_name2(unlang_call_current(request)));
50  log_request_pair_list(L_DBG_LVL_1, request, NULL, &request->request_pairs, NULL);
51 
52  /*
53  * Just push the virtual server onto the stack?
54  *
55  * Except that the caller expects this function to be run
56  * _synchronously_, and all of that needs to be fixed.
57  */
59 
60 #if 0
61  {
62  fr_pair_t *username, *parent_username = NULL;
63  fr_pair_t *vp;
64 
65  username = fr_pair_find_by_num(&request->request_pairs, 0, FR_STRIPPED_USER_NAME);
66  if (!username) username = fr_pair_find_by_num(&request->request_pairs, 0, FR_USER_NAME);
67 
68  if (request->parent) {
69  parent_username = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_STRIPPED_USER_NAME);
70  if (!parent_username) parent_username = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_USER_NAME);
71  }
72 
73  /*
74  * Complain about possible issues related to tunnels.
75  */
76  if (username && parent_username) {
77  /*
78  * Look at the full User-Name with realm.
79  */
80  if (parent_username->da->attr == FR_STRIPPED_USER_NAME) {
81  vp = fr_pair_find_by_num(&request->parent->request_pairs, 0, FR_USER_NAME);
82  if (!vp) goto runit;
83  } else {
84  vp = parent_username;
85  }
86 
87  /*
88  * If the names aren't identical, we do some detailed checks.
89  */
90  if (strcmp(vp->vp_strvalue, username->vp_strvalue) != 0) {
91  char const *outer, *inner;
92 
93  outer = strchr(vp->vp_strvalue, '@');
94 
95  /*
96  * If there's no realm, or there's a user identifier before
97  * the realm name, check the user identifier.
98  *
99  * It SHOULD be "anonymous", or "anonymous@realm"
100  */
101  if (outer) {
102  if ((outer != vp->vp_strvalue) &&
103  ((vp->vp_length < 10) || (memcmp(vp->vp_strvalue, "anonymous@", 10) != 0))) {
104  RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
105  } /* else it is anonymized */
106 
107  /*
108  * Check when there's no realm, and without the trailing '@'
109  */
110  } else if ((vp->vp_length < 9) || (memcmp(vp->vp_strvalue, "anonymous", 9) != 0)) {
111  RWDEBUG("Outer User-Name is not anonymized. User privacy is compromised.");
112 
113  } /* else the user identifier is anonymized */
114 
115  /*
116  * Look for an inner realm, which may or may not exist.
117  */
118  inner = strchr(username->vp_strvalue, '@');
119  if (outer && inner) {
120  outer++;
121  inner++;
122 
123  /*
124  * The realms are different, do
125  * more detailed checks.
126  */
127  if (strcmp(outer, inner) != 0) {
128  size_t outer_len, inner_len;
129 
130  outer_len = vp->vp_length;
131  outer_len -= (outer - vp->vp_strvalue);
132 
133  inner_len = username->vp_length;
134  inner_len -= (inner - username->vp_strvalue);
135 
136  /*
137  * Inner: secure.example.org
138  * Outer: example.org
139  */
140  if (inner_len > outer_len) {
141  char const *suffix;
142 
143  suffix = inner + (inner_len - outer_len) - 1;
144 
145  if ((*suffix != '.') ||
146  (strcmp(suffix + 1, outer) != 0)) {
147  RWDEBUG("Possible spoofing: Inner realm '%s' is not a "
148  "subdomain of the outer realm '%s'", inner, outer);
149  }
150 
151  } else {
152  RWDEBUG("Possible spoofing: Inner realm and "
153  "outer realms are different");
154  }
155  }
156  }
157 
158  } else {
159  RWDEBUG("Outer and inner identities are the same. User privacy is compromised.");
160  }
161  }
162  }
163 
164  if (!request->async) {
165 #ifdef STATIC_ANALYZER
166  if (!request->parent) RETURN_MODULE_FAIL;
167 #endif
168  fr_assert(request->parent != NULL);
169 
170  request->async = talloc_memdup(request, request->parent->async, sizeof(fr_async_t));
171  talloc_set_name_const(request->async, talloc_get_name(request->parent->async));
172  }
173 
174  RDEBUG("server %s {", cf_section_name2(unlang_call_current(request)));
175  request->async->process(&final,
176  MODULE_CTX(module_rlm_by_data(request->async->process_inst), NULL, NULL, NULL),
177  request);
178  RDEBUG("} # server %s", cf_section_name2(unlang_call_current(request)));
179 
180  fr_cond_assert(final == RLM_MODULE_OK);
181 
182  if (!request->reply->code ||
183  (request->reply->code == FR_RADIUS_CODE_ACCESS_REJECT)) {
185  }
186 
187  if (request->reply->code == FR_RADIUS_CODE_ACCESS_CHALLENGE) {
189  }
190 
192 #endif
193 }
194 
195 /*
196  * Debug the packet if requested.
197  */
198 void common_packet_debug(request_t *request, fr_packet_t *packet, fr_pair_list_t *pairs, bool received)
199 {
200 #ifdef WITH_IFINDEX_NAME_RESOLUTION
201  char if_name[IFNAMSIZ];
202 #endif
203 
204  if (!packet) return;
205  if (!RDEBUG_ENABLED) return;
206 
207 
208  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 "
209 #ifdef WITH_IFINDEX_NAME_RESOLUTION
210  "%s%s%s"
211 #endif
212  "length %zu",
213  received ? "Received" : "Sent",
214  packet->code,
215  packet->id,
216  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "[" : "",
217  fr_box_ipaddr(packet->socket.inet.src_ipaddr),
218  packet->socket.inet.src_ipaddr.af == AF_INET6 ? "]" : "",
219  packet->socket.inet.src_port,
220  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "[" : "",
221  fr_box_ipaddr(packet->socket.inet.dst_ipaddr),
222  packet->socket.inet.dst_ipaddr.af == AF_INET6 ? "]" : "",
223  packet->socket.inet.dst_port,
224 #ifdef WITH_IFINDEX_NAME_RESOLUTION
225  packet->socket.inet.ifindex ? "via " : "",
226  packet->socket.inet.ifindex ? fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex) : "",
227  packet->socket.inet.ifindex ? " " : "",
228 #endif
229  packet->data_len);
230 
231  if (received) {
232  log_request_pair_list(L_DBG_LVL_1, request, NULL, pairs, NULL);
233  } else {
234  log_request_proto_pair_list(L_DBG_LVL_1, request, NULL, pairs, NULL);
235  }
236 }
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:198
unlang_action_t rad_virtual_server(rlm_rcode_t *p_result, request_t *request)
Definition: auth.c:47
#define RCSID(id)
Definition: build.h:446
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:1187
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:139
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition: defs.h:35
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:854
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:612
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:830
#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(_mi, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
Definition: module_ctx.h:128
#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