e765b1b8f4e61eb729f9d6d931e029b89ec54717
3 char const *cvs_id_radius
= "$Id: radius.c,v 1.36 2005/06/30 14:31:26 bodea Exp $";
8 #include <sys/socket.h>
12 #include <arpa/inet.h>
14 #include <netinet/in.h>
17 #include "constants.h"
23 extern radiust
*radius
;
24 extern sessiont
*session
;
25 extern tunnelt
*tunnel
;
26 extern configt
*config
;
28 extern ip_filtert
*ip_filters
;
30 // Set up socket for radius requests
34 LOG(3, 0, 0, "Creating %d sockets for RADIUS queries\n", RADIUS_FDS
);
35 radfds
= calloc(sizeof(int), RADIUS_FDS
);
36 for (i
= 0; i
< RADIUS_FDS
; i
++)
39 radfds
[i
] = socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
40 flags
= fcntl(radfds
[i
], F_GETFL
, 0);
41 fcntl(radfds
[i
], F_SETFL
, flags
| O_NONBLOCK
);
45 void radiusclear(uint16_t r
, sessionidt s
)
47 if (s
) sess_local
[s
].radius
= 0;
48 memset(&radius
[r
], 0, sizeof(radius
[r
])); // radius[r].state = RADIUSNULL;
51 static uint16_t get_free_radius()
54 static uint32_t next_radius_id
= 0;
56 for (count
= MAXRADIUS
; count
> 0; --count
)
58 ++next_radius_id
; // Find the next ID to check.
59 if (next_radius_id
>= MAXRADIUS
)
62 if (radius
[next_radius_id
].state
== RADIUSNULL
)
64 return next_radius_id
;
68 LOG(0, 0, 0, "Can't find a free radius session! This is very bad!\n");
72 uint16_t radiusnew(sessionidt s
)
74 uint16_t r
= sess_local
[s
].radius
;
79 LOG(3, s
, session
[s
].tunnel
, "Re-used radius %d\n", r
);
83 if (!(r
= get_free_radius()))
85 LOG(1, s
, session
[s
].tunnel
, "No free RADIUS sessions\n");
86 STAT(radius_overflow
);
90 memset(&radius
[r
], 0, sizeof(radius
[r
]));
91 sess_local
[s
].radius
= r
;
92 radius
[r
].session
= s
;
93 radius
[r
].state
= RADIUSWAIT
;
94 radius
[r
].retry
= TIME
+ 1200; // Wait at least 120 seconds to re-claim this.
96 random_data(radius
[r
].auth
, sizeof(radius
[r
].auth
));
98 LOG(3, s
, session
[s
].tunnel
, "Allocated radius %d\n", r
);
102 // Send a RADIUS request
103 void radiussend(uint16_t r
, uint8_t state
)
105 struct sockaddr_in addr
;
106 uint8_t b
[4096]; // RADIUS packet
114 s
= radius
[r
].session
;
115 if (!config
->numradiusservers
)
117 LOG(0, s
, session
[s
].tunnel
, "No RADIUS servers\n");
120 if (!*config
->radiussecret
)
122 LOG(0, s
, session
[s
].tunnel
, "No RADIUS secret\n");
126 if (state
!= RADIUSAUTH
&& !config
->radius_accounting
)
128 // Radius accounting is turned off
133 if (radius
[r
].state
!= state
)
136 radius
[r
].state
= state
;
137 radius
[r
].retry
= backoff(radius
[r
].try++) + 20; // 3s, 4s, 6s, 10s...
138 LOG(4, s
, session
[s
].tunnel
, "Send RADIUS id %d sock %d state %s try %d\n",
139 r
>> RADIUS_SHIFT
, r
& RADIUS_MASK
,
140 radius_state(radius
[r
].state
), radius
[r
].try);
142 if (radius
[r
].try > config
->numradiusservers
* 2)
146 if (state
== RADIUSAUTH
)
147 sessionshutdown(s
, "RADIUS timeout.", 3, 0);
150 LOG(1, s
, session
[s
].tunnel
, "RADIUS timeout, but in state %s so don't timeout session\n",
151 radius_state(state
));
154 STAT(radius_timeout
);
158 STAT(radius_retries
);
159 radius
[r
].state
= RADIUSWAIT
;
160 radius
[r
].retry
= 100;
164 // contruct RADIUS access request
168 b
[0] = AccessRequest
; // access request
173 b
[0] = AccountingRequest
; // accounting request
176 LOG(0, 0, 0, "Unknown radius state %d\n", state
);
178 b
[1] = r
>> RADIUS_SHIFT
; // identifier
179 memcpy(b
+ 4, radius
[r
].auth
, 16);
184 p
[1] = strlen(session
[s
].user
) + 2;
185 strcpy(p
+ 2, session
[s
].user
);
188 if (state
== RADIUSAUTH
)
192 *p
= 3; // CHAP password
194 p
[2] = radius
[r
].id
; // ID
195 memcpy(p
+ 3, radius
[r
].pass
, 16); // response from CHAP request
197 *p
= 60; // CHAP Challenge
199 memcpy(p
+ 2, radius
[r
].auth
, 16);
204 strcpy(pass
, radius
[r
].pass
);
207 pass
[pl
++] = 0; // pad
216 MD5Update(&ctx
, config
->radiussecret
, strlen(config
->radiussecret
));
218 MD5Update(&ctx
, pass
+ p
- 16, 16);
220 MD5Update(&ctx
, radius
[r
].auth
, 16);
221 MD5Final(hash
, &ctx
);
224 pass
[p
] ^= hash
[p
& 15];
233 memcpy(p
+ 2, pass
, pl
);
237 else if (state
== RADIUSSTART
|| state
== RADIUSSTOP
|| state
== RADIUSINTERIM
)
239 *p
= 40; // accounting type
241 *(uint32_t *) (p
+ 2) = htonl(state
- RADIUSSTART
+ 1); // start=1, stop=2, interim=3
245 *p
= 44; // session ID
247 sprintf(p
+ 2, "%08X%08X", session
[s
].unique_id
, session
[s
].opened
);
249 if (state
== RADIUSSTART
)
253 *(uint32_t *) (p
+ 2) = htonl(time(NULL
) - session
[s
].opened
);
255 sess_local
[s
].last_interim
= time_now
; // Setup "first" Interim
259 *p
= 42; // input octets
261 *(uint32_t *) (p
+ 2) = htonl(session
[s
].cin
);
264 *p
= 43; // output octets
266 *(uint32_t *) (p
+ 2) = htonl(session
[s
].cout
);
268 if (state
== RADIUSSTOP
)
270 *p
= 46; // session time
272 *(uint32_t *) (p
+ 2) = htonl(time(NULL
) - session
[s
].opened
);
276 *p
= 47; // input packets
278 *(uint32_t *) (p
+ 2) = htonl(session
[s
].pin
);
281 *p
= 48; // output packets
283 *(uint32_t *) (p
+ 2) = htonl(session
[s
].pout
);
286 *p
= 52; // input gigawords
288 *(uint32_t *) (p
+ 2) = htonl(session
[s
].cin_wrap
);
291 *p
= 53; // output gigawords
293 *(uint32_t *) (p
+ 2) = htonl(session
[s
].cout_wrap
);
297 if (session
[s
].snoop_ip
&& session
[s
].snoop_port
)
299 *p
= 26; // vendor-specific
300 *(uint32_t *) (p
+ 2) = htonl(9); // Cisco
301 p
[6] = 1; // Cisco-AVPair
302 p
[7] = 2 + sprintf(p
+ 8, "intercept=%s:%d",
303 fmtaddr(session
[s
].snoop_ip
, 0), session
[s
].snoop_port
);
314 *(uint32_t *) (p
+ 2) = htonl(s
);
317 if (s
&& session
[s
].ip
)
319 *p
= 8; // Framed-IP-Address
321 *(uint32_t *) (p
+ 2) = htonl(session
[s
].ip
);
324 if (*session
[s
].called
)
327 p
[1] = strlen(session
[s
].called
) + 2;
328 strcpy(p
+ 2, session
[s
].called
);
331 if (*radius
[r
].calling
)
334 p
[1] = strlen(radius
[r
].calling
) + 2;
335 strcpy(p
+ 2, radius
[r
].calling
);
338 else if (*session
[s
].calling
)
341 p
[1] = strlen(session
[s
].calling
) + 2;
342 strcpy(p
+ 2, session
[s
].calling
);
348 *(uint32_t *)(p
+ 2) = config
->bind_address
;
352 *(uint16_t *) (b
+ 2) = htons(p
- b
);
353 if (state
!= RADIUSAUTH
)
355 // Build auth for accounting packet
360 MD5Update(&ctx
, b
, 4);
361 MD5Update(&ctx
, z
, 16);
362 MD5Update(&ctx
, b
+ 20, (p
- b
) - 20);
363 MD5Update(&ctx
, config
->radiussecret
, strlen(config
->radiussecret
));
364 MD5Final(hash
, &ctx
);
365 memcpy(b
+ 4, hash
, 16);
366 memcpy(radius
[r
].auth
, hash
, 16);
368 memset(&addr
, 0, sizeof(addr
));
369 addr
.sin_family
= AF_INET
;
370 *(uint32_t *) & addr
.sin_addr
= config
->radiusserver
[(radius
[r
].try - 1) % config
->numradiusservers
];
373 uint16_t port
= config
->radiusport
[(radius
[r
].try - 1) % config
->numradiusservers
];
374 // assume RADIUS accounting port is the authentication port +1
375 addr
.sin_port
= htons((state
== RADIUSAUTH
) ? port
: port
+1);
378 LOG_HEX(5, "RADIUS Send", b
, (p
- b
));
379 sendto(radfds
[r
& RADIUS_MASK
], b
, p
- b
, 0, (void *) &addr
, sizeof(addr
));
382 static void handle_avpair(sessionidt s
, uint8_t *avp
, int len
)
385 char *value
= memchr(avp
, '=', len
);
400 if (len
> 2 && (*value
== '"' || *value
== '\'') && value
[len
- 1] == *value
)
406 // copy and null terminate
407 else if (len
< sizeof(tmp
) - 1)
409 memcpy(tmp
, value
, len
);
418 struct param_radius_response p
= { &tunnel
[session
[s
].tunnel
], &session
[s
], key
, value
};
419 run_plugins(PLUGIN_RADIUS_RESPONSE
, &p
);
423 // process RADIUS response
424 void processrad(uint8_t *buf
, int len
, char socket_index
)
426 uint8_t b
[MAXCONTROL
];
438 LOG_HEX(5, "RADIUS Response", buf
, len
);
439 if (len
< 20 || len
< ntohs(*(uint16_t *) (buf
+ 2)))
441 LOG(1, 0, 0, "Duff RADIUS response length %d\n", len
);
445 r_code
= buf
[0]; // response type
446 r_id
= buf
[1]; // radius reply indentifier.
448 len
= ntohs(*(uint16_t *) (buf
+ 2));
449 r
= socket_index
| (r_id
<< RADIUS_SHIFT
);
450 s
= radius
[r
].session
;
451 LOG(3, s
, session
[s
].tunnel
, "Received %s, radius %d response for session %u (%s, id %d)\n",
452 radius_state(radius
[r
].state
), r
, s
, radius_code(r_code
), r_id
);
454 if (!s
&& radius
[r
].state
!= RADIUSSTOP
)
456 LOG(1, s
, session
[s
].tunnel
, " Unexpected RADIUS response\n");
459 if (radius
[r
].state
!= RADIUSAUTH
&& radius
[r
].state
!= RADIUSSTART
460 && radius
[r
].state
!= RADIUSSTOP
&& radius
[r
].state
!= RADIUSINTERIM
)
462 LOG(1, s
, session
[s
].tunnel
, " Unexpected RADIUS response\n");
465 t
= session
[s
].tunnel
;
467 MD5Update(&ctx
, buf
, 4);
468 MD5Update(&ctx
, radius
[r
].auth
, 16);
469 MD5Update(&ctx
, buf
+ 20, len
- 20);
470 MD5Update(&ctx
, config
->radiussecret
, strlen(config
->radiussecret
));
471 MD5Final(hash
, &ctx
);
473 if (memcmp(hash
, buf
+ 4, 16))
475 LOG(0, s
, session
[s
].tunnel
, " Incorrect auth on RADIUS response!! (wrong secret in radius config?)\n");
476 return; // Do nothing. On timeout, it will try the next radius server.
479 if ((radius
[r
].state
== RADIUSAUTH
&& r_code
!= AccessAccept
&& r_code
!= AccessReject
) ||
480 ((radius
[r
].state
== RADIUSSTART
|| radius
[r
].state
== RADIUSSTOP
|| radius
[r
].state
== RADIUSINTERIM
) && r_code
!= AccountingResponse
))
482 LOG(1, s
, session
[s
].tunnel
, " Unexpected RADIUS response %s\n", radius_code(r_code
));
483 return; // We got something we didn't expect. Let the timeouts take
484 // care off finishing the radius session if that's really correct.
487 if (radius
[r
].state
== RADIUSAUTH
)
489 // run post-auth plugin
490 struct param_post_auth packet
= {
494 (r_code
== AccessAccept
),
495 radius
[r
].chap
? PPPCHAP
: PPPPAP
498 run_plugins(PLUGIN_POST_AUTH
, &packet
);
499 r_code
= packet
.auth_allowed
? AccessAccept
: AccessReject
;
501 // process auth response
505 uint8_t *p
= makeppp(b
, sizeof(b
), 0, 0, t
, s
, PPPCHAP
);
506 if (!p
) return; // Abort!
508 *p
= (r_code
== AccessAccept
) ? 3 : 4; // ack/nak
510 *(uint16_t *) (p
+ 2) = ntohs(4); // no message
511 tunnelsend(b
, (p
- b
) + 4, t
); // send it
513 LOG(3, s
, session
[s
].tunnel
, " CHAP User %s authentication %s.\n", session
[s
].user
,
514 (r_code
== AccessAccept
) ? "allowed" : "denied");
519 uint8_t *p
= makeppp(b
, sizeof(b
), 0, 0, t
, s
, PPPPAP
);
520 if (!p
) return; // Abort!
525 *(uint16_t *) (p
+ 2) = ntohs(5);
526 p
[4] = 0; // no message
527 tunnelsend(b
, (p
- b
) + 5, t
); // send it
529 LOG(3, s
, session
[s
].tunnel
, " PAP User %s authentication %s.\n", session
[s
].user
,
530 (r_code
== AccessAccept
) ? "allowed" : "denied");
533 if (r_code
== AccessAccept
)
536 // Extract IP, routes, etc
537 uint8_t *p
= buf
+ 20;
538 uint8_t *e
= buf
+ len
;
539 for (; p
+ 2 <= e
&& p
[1] && p
+ p
[1] <= e
; p
+= p
[1])
544 if (p
[1] < 6) continue;
545 session
[s
].ip
= ntohl(*(uint32_t *) (p
+ 2));
546 session
[s
].ip_pool_index
= -1;
547 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains IP address %s\n",
548 fmtaddr(htonl(session
[s
].ip
), 0));
550 if (session
[s
].ip
== 0xFFFFFFFE)
551 session
[s
].ip
= 0; // assign from pool
556 if (p
[1] < 6) continue;
557 session
[s
].dns1
= ntohl(*(uint32_t *) (p
+ 2));
558 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains primary DNS address %s\n",
559 fmtaddr(htonl(session
[s
].dns1
), 0));
564 if (p
[1] < 6) continue;
565 session
[s
].dns2
= ntohl(*(uint32_t *) (p
+ 2));
566 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains secondary DNS address %s\n",
567 fmtaddr(htonl(session
[s
].dns2
), 0));
572 in_addr_t ip
= 0, mask
= 0;
576 uint8_t *e
= p
+ p
[1];
577 while (n
< e
&& (isdigit(*n
) || *n
== '.'))
585 u
= u
* 10 + *n
- '0';
592 while (n
< e
&& isdigit(*n
))
593 bits
= bits
* 10 + *n
++ - '0';
594 mask
= (( -1) << (32 - bits
));
596 else if ((ip
>> 24) < 128)
598 else if ((ip
>> 24) < 192)
603 if (routes
== MAXROUTE
)
605 LOG(1, s
, session
[s
].tunnel
, " Too many routes\n");
609 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains route for %s/%s\n",
610 fmtaddr(htonl(ip
), 0), fmtaddr(htonl(mask
), 1));
612 session
[s
].route
[routes
].ip
= ip
;
613 session
[s
].route
[routes
].mask
= mask
;
620 char *filter
= p
+ 2;
626 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains Filter-Id \"%.*s\"\n", l
, filter
);
627 if ((suffix
= memchr(filter
, '.', l
)))
629 int b
= suffix
- filter
;
630 if (l
- b
== 3 && !memcmp("in", suffix
+1, 2))
631 fp
= &session
[s
].filter_in
;
632 else if (l
- b
== 4 && !memcmp("out", suffix
+1, 3))
633 fp
= &session
[s
].filter_out
;
640 LOG(3, s
, session
[s
].tunnel
, " Invalid filter\n");
644 if ((f
= find_filter(filter
, l
)) < 0 || !*ip_filters
[f
].name
)
646 LOG(3, s
, session
[s
].tunnel
, " Unknown filter\n");
651 ip_filters
[f
].used
++;
654 else if (*p
== 26 && p
[1] >= 7)
656 // Vendor-Specific Attribute
657 int vendor
= ntohl(*(int *)(p
+ 2));
658 char attrib
= *(p
+ 6);
659 int attrib_length
= *(p
+ 7) - 2;
661 LOG(3, s
, session
[s
].tunnel
, " Radius reply contains Vendor-Specific. Vendor=%d Attrib=%d Length=%d\n", vendor
, attrib
, attrib_length
);
662 if (vendor
!= 9 || attrib
!= 1)
664 LOG(3, s
, session
[s
].tunnel
, " Unknown vendor-specific\n");
668 if (attrib_length
> 0)
670 LOG(3, s
, session
[s
].tunnel
, " Cisco-AVPair value: %.*s\n",
671 attrib_length
, p
+ 8);
673 handle_avpair(s
, p
+ 8, attrib_length
);
682 uint8_t *e
= p
+ p
[1];
683 uint8_t *m
= strchr(n
, '/');
686 inet_pton(AF_INET6
, n
, &r6
);
689 while (m
< e
&& isdigit(*m
)) {
690 prefixlen
= prefixlen
* 10 + *m
++ - '0';
695 LOG(3, s
, session
[s
].tunnel
,
696 " Radius reply contains route for %s/%d\n",
698 session
[s
].ipv6route
= r6
;
699 session
[s
].ipv6prefixlen
= prefixlen
;
704 else if (r_code
== AccessReject
)
706 LOG(2, s
, session
[s
].tunnel
, " Authentication rejected for %s\n", session
[s
].user
);
707 sessionkill(s
, "Authentication rejected");
711 if (!session
[s
].dns1
&& config
->default_dns1
)
713 session
[s
].dns1
= htonl(config
->default_dns1
);
714 LOG(3, s
, t
, " Sending dns1 = %s\n", fmtaddr(config
->default_dns1
, 0));
716 if (!session
[s
].dns2
&& config
->default_dns2
)
718 session
[s
].dns2
= htonl(config
->default_dns2
);
719 LOG(3, s
, t
, " Sending dns2 = %s\n", fmtaddr(config
->default_dns2
, 0));
722 // Valid Session, set it up
723 session
[s
].unique_id
= 0;
728 // An ack for a stop or start record.
729 LOG(3, s
, t
, " RADIUS accounting ack recv in state %s\n", radius_state(radius
[r
].state
));
734 // finished with RADIUS
738 // Send a retry for RADIUS/CHAP message
739 void radiusretry(uint16_t r
)
741 sessionidt s
= radius
[r
].session
;
746 if (s
) t
= session
[s
].tunnel
;
748 switch (radius
[r
].state
)
750 case RADIUSCHAP
: // sending CHAP down PPP
754 sendipcp(t
, s
); // send IPCP
756 case RADIUSAUTH
: // sending auth to RADIUS server
757 radiussend(r
, RADIUSAUTH
);
759 case RADIUSSTART
: // sending start accounting to RADIUS server
760 radiussend(r
, RADIUSSTART
);
762 case RADIUSSTOP
: // sending stop accounting to RADIUS server
763 radiussend(r
, RADIUSSTOP
);
765 case RADIUSINTERIM
: // sending interim accounting to RADIUS server
766 radiussend(r
, RADIUSINTERIM
);
769 case RADIUSNULL
: // Not in use
770 case RADIUSWAIT
: // waiting timeout before available, in case delayed reply from RADIUS server
771 // free up RADIUS task
773 LOG(3, s
, session
[s
].tunnel
, "Freeing up radius session %d\n", r
);
780 void processdae(uint8_t *buf
, int len
, struct sockaddr_in
*addr
, int alen
)
782 int i
, r_code
, r_id
, length
, attribute_length
;
783 uint8_t vector
[16], hash
[16], *packet
, attribute
;
785 char username
[MAXUSER
] = "";
795 int avpair_len
[sizeof(avpair
)/sizeof(*avpair
)];
800 LOG(3, 0, 0, "DAE request from %s\n", fmtaddr(addr
->sin_addr
.s_addr
, 0));
801 LOG_HEX(5, "DAE Request", buf
, len
);
803 if (len
< 20 || len
< ntohs(*(uint16_t *) (buf
+ 2)))
805 LOG(1, 0, 0, "Duff DAE request length %d\n", len
);
809 r_code
= buf
[0]; // request type
810 r_id
= buf
[1]; // radius indentifier.
812 if (r_code
!= DisconnectRequest
&& r_code
!= CoARequest
)
814 LOG(1, 0, 0, "Unrecognised DAE request %s\n", radius_code(r_code
));
818 if (!config
->cluster_iam_master
)
820 master_forward_dae_packet(buf
, len
, addr
->sin_addr
.s_addr
, addr
->sin_port
);
824 len
= ntohs(*(uint16_t *) (buf
+ 2));
826 LOG(3, 0, 0, "Received DAE %s, id %d\n", radius_code(r_code
), r_id
);
828 // check authenticator
829 memcpy(vector
, buf
+ 4, 16);
830 memset(buf
+ 4, 0, 16);
832 i
= strlen(config
->radiussecret
);
836 MD5Update(&ctx
, buf
, len
);
837 MD5Update(&ctx
, buf
, config
->radiussecret
, i
);
838 MD5Final(hash
, &ctx
);
839 if (memcmp(hash
, vector
, 16) != 0)
841 LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n");
851 attribute
= *packet
++;
852 attribute_length
= *packet
++;
853 if (attribute_length
< 2)
856 length
-= attribute_length
;
857 attribute_length
-= 2;
860 case 1: /* username */
861 len
= attribute_length
< MAXUSER
? attribute_length
: MAXUSER
- 1;
862 memcpy(username
, packet
, len
);
864 LOG(4, 0, 0, " Received DAE User-Name: %s\n", username
);
867 case 4: /* nas ip address */
868 nas
= *(uint32_t *) packet
; // net order
869 if (nas
!= config
->bind_address
)
870 error
= 403; // NAS identification mismatch
872 LOG(4, 0, 0, " Received DAE NAS-IP-Address: %s\n", fmtaddr(nas
, 0));
875 case 5: /* nas port */
876 port
= ntohl(*(uint32_t *) packet
);
877 if (port
< 1 || port
> MAXSESSION
)
880 LOG(4, 0, 0, " Received DAE NAS-Port: %u\n", port
);
883 case 6: /* service type */
885 uint32_t service_type
= ntohl(*(uint32_t *) packet
);
886 auth_only
= service_type
== 8; // Authenticate only
888 LOG(4, 0, 0, " Received DAE Service-Type: %u\n", service_type
);
892 case 8: /* ip address */
893 ip
= *(uint32_t *) packet
; // net order
894 LOG(4, 0, 0, " Received DAE Framed-IP-Address: %s\n", fmtaddr(ip
, 0));
897 case 11: /* filter id */
898 LOG(4, 0, 0, " Received DAE Filter-Id: %.*s\n", attribute_length
, packet
);
899 if (!(p
= memchr(packet
, '.', attribute_length
)))
901 error
= 404; // invalid request
906 i
= find_filter(packet
, len
);
907 if (i
< 0 || !*ip_filters
[i
].name
)
913 if (!memcmp(p
, ".in", attribute_length
- len
))
915 else if (!memcmp(p
, ".out", attribute_length
- len
))
922 case 26: /* vendor specific */
923 if (attribute_length
>= 6
924 && ntohl(*(uint32_t *) packet
) == 9 // Cisco
925 && *(packet
+ 4) == 1 // Cisco-AVPair
926 && *(packet
+ 5) >= 2) // length
928 int len
= *(packet
+ 5) - 2;
929 uint8_t *a
= packet
+ 6;
931 LOG(4, 0, 0, " Received DAE Cisco-AVPair: %.*s\n", len
, a
);
932 if (avp
< sizeof(avpair
)/sizeof(*avpair
) - 1)
935 avpair_len
[avp
++] = len
;
941 packet
+= attribute_length
;
944 if (!error
&& auth_only
)
946 if (fin
!= -1 || fout
!= -1 || avp
)
947 error
= 401; // unsupported attribute
949 error
= 405; // unsupported service
952 if (!error
&& !(port
|| ip
|| *username
))
953 error
= 402; // missing attribute
955 // exact match for SID if given
959 if (!session
[s
].opened
)
960 error
= 503; // not found
965 // find/check session by IP
967 if (!i
|| (s
&& s
!= i
)) // not found or mismatching port
973 if (!error
&& *username
)
977 if (strcmp(session
[s
].user
, username
))
980 else if (!(s
= sessionbyuser(username
)))
984 t
= session
[s
].tunnel
;
988 case DisconnectRequest
: // Packet of Disconnect/Death
991 r_code
= DisconnectNAK
;
995 LOG(3, s
, t
, " DAE Disconnect %d (%s)\n", s
, session
[s
].user
);
996 r_code
= DisconnectACK
;
998 sessionshutdown(s
, "Requested by PoD", 3, 0); // disconnect session
1001 case CoARequest
: // Change of Authorization
1008 LOG(3, s
, t
, " DAE Change %d (%s)\n", s
, session
[s
].user
);
1013 struct param_radius_reset p
= { &tunnel
[session
[s
].tunnel
], &session
[s
] };
1014 run_plugins(PLUGIN_RADIUS_RESET
, &p
);
1021 LOG(3, s
, t
, " Filter in %d (%s)\n", fin
, ip_filters
[fin
- 1].name
);
1026 LOG(3, s
, t
, " Filter out %d (%s)\n", fout
, ip_filters
[fout
- 1].name
);
1028 filter_session(s
, fin
, fout
);
1030 // process cisco av-pair(s)
1031 for (i
= 0; i
< avp
; i
++)
1033 LOG(3, s
, t
, " Cisco-AVPair: %.*s\n", avpair_len
[i
], avpair
[i
]);
1034 handle_avpair(s
, avpair
[i
], avpair_len
[i
]);
1037 cluster_send_session(s
);
1046 memset(packet
, 0, 16);
1056 *(uint32_t *) packet
= htonl(error
);
1060 *((uint16_t *)(buf
+ 2)) = htons(len
);
1063 i
= strlen(config
->radiussecret
);
1067 MD5Update(&ctx
, buf
, len
);
1068 MD5Update(&ctx
, config
->radiussecret
, i
);
1069 MD5Final(hash
, &ctx
);
1070 memcpy(buf
+ 4, hash
, 16);
1072 LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code
), r_id
);
1074 // send DAE response
1075 if (sendto(daefd
, buf
, len
, MSG_DONTWAIT
| MSG_NOSIGNAL
, (struct sockaddr
*) addr
, alen
) < 0)
1076 LOG(0, 0, 0, "Error sending DAE response packet: %s\n", strerror(errno
));