119 |
/* ************************************************************************* */ |
/* ************************************************************************* */ |
120 |
/* Reply functions. Possibly these should go to libclient? */ |
/* Reply functions. Possibly these should go to libclient? */ |
121 |
|
|
122 |
|
/* Send the request */ |
123 |
|
static int |
124 |
|
proxy_send_pdu(int fd, RADIUS_SERVER *server, RADIUS_REQ *radreq, |
125 |
|
void *pdu, size_t size) |
126 |
|
{ |
127 |
|
struct sockaddr_in sin; |
128 |
|
|
129 |
|
memset(&sin, 0, sizeof (sin)); |
130 |
|
sin.sin_family = AF_INET; |
131 |
|
sin.sin_addr.s_addr = htonl(server->addr); |
132 |
|
|
133 |
|
sin.sin_port = htons((radreq->code == RT_AUTHENTICATION_REQUEST) ? |
134 |
|
server->port[PORT_AUTH] : server->port[PORT_ACCT]); |
135 |
|
|
136 |
|
debug(1, ("Proxying id %d to %lx", |
137 |
|
radreq->id, (u_long)server->addr)); |
138 |
|
|
139 |
|
return sendto(fd, pdu, size, 0, (struct sockaddr *)&sin, sizeof(sin)); |
140 |
|
} |
141 |
|
|
142 |
int |
int |
143 |
proxy_send_request(int fd, RADIUS_REQ *radreq) |
proxy_send_request(int fd, RADIUS_REQ *radreq) |
144 |
{ |
{ |
145 |
VALUE_PAIR *plist, *p; |
VALUE_PAIR *plist, *p; |
|
PROXY_STATE *proxy_state; |
|
146 |
char vector[AUTH_VECTOR_LEN]; |
char vector[AUTH_VECTOR_LEN]; |
147 |
void *pdu; |
void *pdu; |
148 |
size_t size; |
size_t size; |
|
struct sockaddr_in sin; |
|
149 |
RADIUS_SERVER *server; |
RADIUS_SERVER *server; |
150 |
|
int rc; |
151 |
|
|
152 |
if (radreq->attempt_no > radreq->realm->queue->retries) { |
if (radreq->attempt_no > radreq->realm->queue->retries) { |
153 |
radreq->server_no++; |
radreq->server_no++; |
176 |
|| p->attribute == DA_CHAP_PASSWORD) |
|| p->attribute == DA_CHAP_PASSWORD) |
177 |
passwd_recode(p, server->secret, vector, radreq); |
passwd_recode(p, server->secret, vector, radreq); |
178 |
} |
} |
|
|
|
|
/* Add a proxy-pair to the end of the request. */ |
|
|
p = avp_alloc(); |
|
|
p->name = "Proxy-State"; |
|
|
p->attribute = DA_PROXY_STATE; |
|
|
p->type = TYPE_STRING; |
|
|
p->avp_strlength = sizeof(PROXY_STATE); |
|
|
p->avp_strvalue = emalloc(p->avp_strlength); |
|
|
|
|
|
proxy_state = (PROXY_STATE *)p->avp_strvalue; |
|
|
|
|
|
proxy_state->ref_ip = ref_ip; |
|
|
proxy_state->client_ip = radreq->ipaddr; |
|
|
proxy_state->id = radreq->id; |
|
|
proxy_state->proxy_id = radreq->server_id; |
|
|
proxy_state->remote_ip = server->addr; |
|
|
|
|
|
avl_add_pair(&plist, p); |
|
179 |
|
|
180 |
|
if (!envar_lookup_int(radreq->realm->args, "retransmit", 0)) { |
181 |
|
PROXY_STATE *proxy_state; |
182 |
|
|
183 |
|
/* Add a proxy-pair to the end of the request. */ |
184 |
|
p = avp_alloc(); |
185 |
|
p->name = "Proxy-State"; |
186 |
|
p->attribute = DA_PROXY_STATE; |
187 |
|
p->type = TYPE_STRING; |
188 |
|
p->avp_strlength = sizeof(PROXY_STATE); |
189 |
|
p->avp_strvalue = emalloc(p->avp_strlength); |
190 |
|
|
191 |
|
proxy_state = (PROXY_STATE *)p->avp_strvalue; |
192 |
|
|
193 |
|
proxy_state->ref_ip = ref_ip; |
194 |
|
proxy_state->client_ip = radreq->ipaddr; |
195 |
|
proxy_state->id = radreq->id; |
196 |
|
proxy_state->proxy_id = radreq->server_id; |
197 |
|
proxy_state->remote_ip = server->addr; |
198 |
|
|
199 |
|
avl_add_pair(&plist, p); |
200 |
|
} |
201 |
|
|
202 |
/* Create the pdu */ |
/* Create the pdu */ |
203 |
size = rad_create_pdu(&pdu, radreq->code, |
size = rad_create_pdu(&pdu, radreq->code, |
204 |
radreq->server_id, |
radreq->server_id, |
229 |
efree(upd); |
efree(upd); |
230 |
} |
} |
231 |
|
|
232 |
if (size > 0) { |
rc = proxy_send_pdu(fd, server, radreq, pdu, size); |
233 |
/* Send the request */ |
efree(pdu); |
234 |
memset(&sin, 0, sizeof (sin)); |
return rc; |
|
sin.sin_family = AF_INET; |
|
|
sin.sin_addr.s_addr = htonl(server->addr); |
|
|
|
|
|
sin.sin_port = htons( |
|
|
(radreq->code == RT_AUTHENTICATION_REQUEST) ? |
|
|
server->port[PORT_AUTH] : server->port[PORT_ACCT]); |
|
|
|
|
|
debug(1, ("Proxying id %d to %lx", |
|
|
radreq->id, (u_long)server->addr)); |
|
|
|
|
|
sendto(fd, pdu, size, 0, (struct sockaddr *)&sin, sizeof(sin)); |
|
|
} |
|
|
return size; |
|
235 |
} |
} |
236 |
|
|
237 |
/* ************************************************************************* */ |
/* ************************************************************************* */ |
238 |
/* Interface functions */ |
/* Interface functions */ |
239 |
|
|
240 |
|
static REALM * |
241 |
|
proxy_lookup_realm(RADIUS_REQ *req, char *name) |
242 |
|
{ |
243 |
|
REALM *realm = realm_lookup_name(name); |
244 |
|
|
245 |
|
if (realm) { |
246 |
|
char *var = NULL; |
247 |
|
switch (req->code) { |
248 |
|
case RT_AUTHENTICATION_REQUEST: |
249 |
|
var = "auth"; |
250 |
|
break; |
251 |
|
|
252 |
|
case RT_ACCOUNTING_REQUEST: |
253 |
|
var = "acct"; |
254 |
|
break; |
255 |
|
|
256 |
|
default: |
257 |
|
/* Should not happen.. */ |
258 |
|
insist_fail("unexpected request code"); |
259 |
|
} |
260 |
|
|
261 |
|
if (envar_lookup_int(realm->args, var, 1) == 0) |
262 |
|
realm = NULL; |
263 |
|
} |
264 |
|
return realm; |
265 |
|
} |
266 |
|
|
267 |
/* Relay the request to a remote server |
/* Relay the request to a remote server |
268 |
Returns: 1 success (we reply, caller returns without replying) |
Returns: 1 success (we reply, caller returns without replying) |
269 |
0 fail (caller falls through to normal processing) |
0 fail (caller falls through to normal processing) |
273 |
proxy_send(REQUEST *req) |
proxy_send(REQUEST *req) |
274 |
{ |
{ |
275 |
RADIUS_REQ *radreq = req->data; |
RADIUS_REQ *radreq = req->data; |
|
char *saved_username; |
|
276 |
char *username; |
char *username; |
277 |
VALUE_PAIR *namepair; |
VALUE_PAIR *namepair; |
278 |
VALUE_PAIR *vp; |
VALUE_PAIR *vp; |
284 |
if (avp_null_string(namepair)) |
if (avp_null_string(namepair)) |
285 |
return 0; |
return 0; |
286 |
|
|
|
saved_username = estrdup(namepair->avp_strvalue); |
|
287 |
username = namepair->avp_strvalue; |
username = namepair->avp_strvalue; |
288 |
|
|
289 |
/* Find the realm from the _end_ so that we can cascade realms: |
/* Find the realm from the _end_ so that we can cascade realms: |
297 |
|
|
298 |
if ((realmname = strrchr(username, '@')) == NULL) { |
if ((realmname = strrchr(username, '@')) == NULL) { |
299 |
if ((realm = realm_lookup_name("NOREALM")) == NULL) { |
if ((realm = realm_lookup_name("NOREALM")) == NULL) { |
|
efree(saved_username); |
|
300 |
return 0; |
return 0; |
301 |
} |
} |
302 |
} else if ((realm = realm_lookup_name(realmname + 1)) == NULL) { |
} else if ((realm = proxy_lookup_realm(radreq, realmname + 1)) |
303 |
|
== NULL) { |
304 |
/* If the realm is not found, we treat it as usual. */ |
/* If the realm is not found, we treat it as usual. */ |
|
efree(saved_username); |
|
|
return 0; |
|
|
} else if (realm->queue == NULL) { /* This is a LOCAL realm */ |
|
|
if (realm->striprealm) { |
|
|
*realmname = 0; |
|
|
namepair->avp_strlength = strlen(namepair->avp_strvalue); |
|
|
} |
|
|
efree(saved_username); |
|
305 |
return 0; |
return 0; |
306 |
} |
} |
307 |
|
|
308 |
radreq->realm = realm; |
if (realmname && realm_strip_p(realm)) { |
309 |
if (realmname) { |
*realmname = 0; |
310 |
if (realm->striprealm) |
namepair->avp_strlength = strlen(namepair->avp_strvalue); |
311 |
*realmname = 0; |
} |
312 |
} |
|
313 |
|
if (realm->queue == NULL) /* This is a LOCAL realm */ |
314 |
if (username[0]==0) |
return 0; |
|
abort(); |
|
|
string_replace(&namepair->avp_strvalue, username); |
|
|
if (namepair->avp_strvalue[0]==0) |
|
|
abort(); |
|
|
namepair->avp_strlength = strlen(namepair->avp_strvalue); |
|
315 |
|
|
316 |
|
radreq->realm = realm; |
317 |
radreq->server_no = 0; |
radreq->server_no = 0; |
318 |
radreq->attempt_no = 0; |
radreq->attempt_no = 0; |
319 |
radreq->remote_user = estrdup(username); |
/* Actual user name may be altered, but the remote user name |
320 |
|
should remain the same */ |
321 |
|
radreq->remote_user = estrdup(username); |
322 |
|
|
323 |
/* If there is no DA_CHAP_CHALLENGE attribute but there |
/* If there is no DA_CHAP_CHALLENGE attribute but there |
324 |
is a DA_CHAP_PASSWORD we need to add it since we can't |
is a DA_CHAP_PASSWORD we need to add it since we can't |
338 |
avl_add_pair(&radreq->request, vp); |
avl_add_pair(&radreq->request, vp); |
339 |
} |
} |
340 |
|
|
|
efree(saved_username); |
|
|
|
|
341 |
proxy_send_request(req->fd, radreq); |
proxy_send_request(req->fd, radreq); |
342 |
|
|
343 |
|
if (envar_lookup_int(realm->args, "retransmit", 0)) |
344 |
|
return 0; |
345 |
|
|
346 |
return 1; |
return 1; |
347 |
} |
} |
348 |
|
|