X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/4f253feef08f01c03bc63f70f9de3937541ccd79..b2bd9655946aa73a31b5e5d9baf417cd38938cd8:/radius.c?ds=inline diff --git a/radius.c b/radius.c index 98ea391..6cb9e16 100644 --- a/radius.c +++ b/radius.c @@ -1,6 +1,6 @@ // L2TPNS Radius Stuff -char const *cvs_id_radius = "$Id: radius.c,v 1.34 2005/06/28 14:48:28 bodea Exp $"; +char const *cvs_id_radius = "$Id: radius.c,v 1.47 2005/12/19 06:18:13 bodea Exp $"; #include #include @@ -27,6 +27,20 @@ extern configt *config; extern int *radfds; extern ip_filtert *ip_filters; +static const hasht zero; + +static void calc_auth(const void *buf, size_t len, const uint8_t *in, uint8_t *out) +{ + MD5_CTX ctx; + + MD5_Init(&ctx); + MD5_Update(&ctx, (void *)buf, 4); // code, id, length + MD5_Update(&ctx, (void *)in, 16); // auth + MD5_Update(&ctx, (void *)(buf + 20), len - 20); + MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret)); + MD5_Final(out, &ctx); +} + // Set up socket for radius requests void initrad(void) { @@ -182,7 +196,7 @@ void radiussend(uint16_t r, uint8_t state) { *p = 1; // user name p[1] = strlen(session[s].user) + 2; - strcpy(p + 2, session[s].user); + strcpy((char *) p + 2, session[s].user); p += p[1]; } if (state == RADIUSAUTH) @@ -212,13 +226,13 @@ void radiussend(uint16_t r, uint8_t state) while (p < pl) { MD5_CTX ctx; - MD5Init(&ctx); - MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); + MD5_Init(&ctx); + MD5_Update(&ctx, config->radiussecret, strlen(config->radiussecret)); if (p) - MD5Update(&ctx, pass + p - 16, 16); + MD5_Update(&ctx, pass + p - 16, 16); else - MD5Update(&ctx, radius[r].auth, 16); - MD5Final(hash, &ctx); + MD5_Update(&ctx, radius[r].auth, 16); + MD5_Final(hash, &ctx); do { pass[p] ^= hash[p & 15]; @@ -244,7 +258,7 @@ void radiussend(uint16_t r, uint8_t state) { *p = 44; // session ID p[1] = 18; - sprintf(p + 2, "%08X%08X", session[s].unique_id, session[s].opened); + sprintf((char *) p + 2, "%08X%08X", session[s].unique_id, session[s].opened); p += p[1]; if (state == RADIUSSTART) { // start @@ -265,13 +279,11 @@ void radiussend(uint16_t r, uint8_t state) p[1] = 6; *(uint32_t *) (p + 2) = htonl(session[s].cout); p += p[1]; - if (state == RADIUSSTOP) - { - *p = 46; // session time - p[1] = 6; - *(uint32_t *) (p + 2) = htonl(time(NULL) - session[s].opened); - p += p[1]; - } + + *p = 46; // session time + p[1] = 6; + *(uint32_t *) (p + 2) = htonl(time(NULL) - session[s].opened); + p += p[1]; *p = 47; // input packets p[1] = 6; @@ -294,25 +306,28 @@ void radiussend(uint16_t r, uint8_t state) p += p[1]; } - if (session[s].snoop_ip && session[s].snoop_port) { - *p = 26; // vendor-specific - *(uint32_t *) (p + 2) = htonl(9); // Cisco - p[6] = 1; // Cisco-AVPair - p[7] = 2 + sprintf(p + 8, "intercept=%s:%d", - fmtaddr(session[s].snoop_ip, 0), session[s].snoop_port); - - p[1] = p[7] + 6; - p += p[1]; + struct param_radius_account acct = { &tunnel[session[s].tunnel], &session[s], &p }; + run_plugins(PLUGIN_RADIUS_ACCOUNT, &acct); } } } if (s) { - *p = 5; // NAS-Port + *p = 5; // NAS-Port p[1] = 6; *(uint32_t *) (p + 2) = htonl(s); p += p[1]; + + *p = 6; // Service-Type + p[1] = 6; + *(uint32_t *) (p + 2) = htonl(2); // Framed-User + p += p[1]; + + *p = 7; // Framed-Protocol + p[1] = 6; + *(uint32_t *) (p + 2) = htonl(1); // PPP + p += p[1]; } if (s && session[s].ip) { @@ -321,25 +336,42 @@ void radiussend(uint16_t r, uint8_t state) *(uint32_t *) (p + 2) = htonl(session[s].ip); p += p[1]; } + if (s && session[s].route[0].ip) + { + int r; + for (r = 0; s && r < MAXROUTE && session[s].route[r].ip; r++) + { + int width = 32; + if (session[s].route[r].mask) + { + int mask = session[s].route[r].mask; + while (!(mask & 1)) + { + width--; + mask >>= 1; + } + } + + *p = 22; // Framed-Route + p[1] = sprintf((char *) p + 2, "%s/%d %s 1", + fmtaddr(htonl(session[s].route[r].ip), 0), + width, fmtaddr(htonl(session[s].ip), 1)) + 2; + + p += p[1]; + } + } if (*session[s].called) { *p = 30; // called p[1] = strlen(session[s].called) + 2; - strcpy(p + 2, session[s].called); + strcpy((char *) p + 2, session[s].called); p += p[1]; } - if (*radius[r].calling) - { - *p = 31; // calling - p[1] = strlen(radius[r].calling) + 2; - strcpy(p + 2, radius[r].calling); - p += p[1]; - } - else if (*session[s].calling) + if (*session[s].calling) { *p = 31; // calling p[1] = strlen(session[s].calling) + 2; - strcpy(p + 2, session[s].calling); + strcpy((char *) p + 2, session[s].calling); p += p[1]; } // NAS-IP-Address @@ -352,18 +384,9 @@ void radiussend(uint16_t r, uint8_t state) *(uint16_t *) (b + 2) = htons(p - b); if (state != RADIUSAUTH) { - // Build auth for accounting packet - char z[16] = {0}; - char hash[16] = {0}; - MD5_CTX ctx; - MD5Init(&ctx); - MD5Update(&ctx, b, 4); - MD5Update(&ctx, z, 16); - MD5Update(&ctx, b + 20, (p - b) - 20); - MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); - MD5Final(hash, &ctx); - memcpy(b + 4, hash, 16); - memcpy(radius[r].auth, hash, 16); + // Build auth for accounting packet + calc_auth(b, p - b, zero, b + 4); + memcpy(radius[r].auth, b + 4, 16); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; @@ -381,9 +404,9 @@ void radiussend(uint16_t r, uint8_t state) static void handle_avpair(sessionidt s, uint8_t *avp, int len) { - char *key = avp; - char *value = memchr(avp, '=', len); - char tmp[2048] = ""; + uint8_t *key = avp; + uint8_t *value = memchr(avp, '=', len); + uint8_t tmp[2048] = ""; if (value) { @@ -415,7 +438,7 @@ static void handle_avpair(sessionidt s, uint8_t *avp, int len) // Run hooks { - struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], key, value }; + struct param_radius_response p = { &tunnel[session[s].tunnel], &session[s], (char *) key, (char *) value }; run_plugins(PLUGIN_RADIUS_RESPONSE, &p); } } @@ -423,8 +446,7 @@ static void handle_avpair(sessionidt s, uint8_t *avp, int len) // process RADIUS response void processrad(uint8_t *buf, int len, char socket_index) { - uint8_t b[MAXCONTROL]; - MD5_CTX ctx; + uint8_t b[MAXETHER]; uint16_t r; sessionidt s; tunnelidt t = 0; @@ -463,12 +485,7 @@ void processrad(uint8_t *buf, int len, char socket_index) return; } t = session[s].tunnel; - MD5Init(&ctx); - MD5Update(&ctx, buf, 4); - MD5Update(&ctx, radius[r].auth, 16); - MD5Update(&ctx, buf + 20, len - 20); - MD5Update(&ctx, config->radiussecret, strlen(config->radiussecret)); - MD5Final(hash, &ctx); + calc_auth(buf, len, radius[r].auth, hash); do { if (memcmp(hash, buf + 4, 16)) { @@ -502,7 +519,7 @@ void processrad(uint8_t *buf, int len, char socket_index) if (radius[r].chap) { // CHAP - uint8_t *p = makeppp(b, sizeof(b), 0, 0, t, s, PPPCHAP); + uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPCHAP); if (!p) return; // Abort! *p = (r_code == AccessAccept) ? 3 : 4; // ack/nak @@ -516,7 +533,7 @@ void processrad(uint8_t *buf, int len, char socket_index) else { // PAP - uint8_t *p = makeppp(b, sizeof(b), 0, 0, t, s, PPPPAP); + uint8_t *p = makeppp(b, sizeof(b), 0, 0, s, t, PPPPAP); if (!p) return; // Abort! // ack/nak @@ -617,7 +634,7 @@ void processrad(uint8_t *buf, int len, char socket_index) else if (*p == 11) { // Filter-Id - char *filter = p + 2; + char *filter = (char *) p + 2; int l = p[1] - 2; char *suffix; int f; @@ -680,10 +697,10 @@ void processrad(uint8_t *buf, int len, char socket_index) int prefixlen; uint8_t *n = p + 2; uint8_t *e = p + p[1]; - uint8_t *m = strchr(n, '/'); + uint8_t *m = memchr(n, '/', e - p); *m++ = 0; - inet_pton(AF_INET6, n, &r6); + inet_pton(AF_INET6, (char *) n, &r6); prefixlen = 0; while (m < e && isdigit(*m)) { @@ -710,18 +727,18 @@ void processrad(uint8_t *buf, int len, char socket_index) if (!session[s].dns1 && config->default_dns1) { - session[s].dns1 = htonl(config->default_dns1); + session[s].dns1 = ntohl(config->default_dns1); LOG(3, s, t, " Sending dns1 = %s\n", fmtaddr(config->default_dns1, 0)); } if (!session[s].dns2 && config->default_dns2) { - session[s].dns2 = htonl(config->default_dns2); + session[s].dns2 = ntohl(config->default_dns2); LOG(3, s, t, " Sending dns2 = %s\n", fmtaddr(config->default_dns2, 0)); } // Valid Session, set it up session[s].unique_id = 0; - sessionsetup(t, s); + sessionsetup(s, t); } else { @@ -748,22 +765,13 @@ void radiusretry(uint16_t r) switch (radius[r].state) { case RADIUSCHAP: // sending CHAP down PPP - sendchap(t, s); - break; - case RADIUSIPCP: - sendipcp(t, s); // send IPCP + sendchap(s, t); break; case RADIUSAUTH: // sending auth to RADIUS server - radiussend(r, RADIUSAUTH); - break; case RADIUSSTART: // sending start accounting to RADIUS server - radiussend(r, RADIUSSTART); - break; case RADIUSSTOP: // sending stop accounting to RADIUS server - radiussend(r, RADIUSSTOP); - break; case RADIUSINTERIM: // sending interim accounting to RADIUS server - radiussend(r, RADIUSINTERIM); + radiussend(r, radius[r].state); break; default: case RADIUSNULL: // Not in use @@ -780,8 +788,8 @@ extern int daefd; void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) { int i, r_code, r_id, length, attribute_length; - uint8_t vector[16], hash[16], *packet, attribute; - MD5_CTX ctx; + uint8_t *packet, attribute; + hasht hash; char username[MAXUSER] = ""; in_addr_t nas = 0; in_addr_t ip = 0; @@ -798,18 +806,6 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) uint8_t *p; LOG(3, 0, 0, "DAE request from %s\n", fmtaddr(addr->sin_addr.s_addr, 0)); - - // check if DAE is from RADIUS server - for (i = 0; i < config->numradiusservers; i++) - if (config->radiusserver[i] == addr -> sin_addr.s_addr) - break; - - if (i >= config->numradiusservers) - { - LOG(1, 0, 0, "Unknown DAE client %s\n", fmtaddr(addr->sin_addr.s_addr, 0)); - return; - } - LOG_HEX(5, "DAE Request", buf, len); if (len < 20 || len < ntohs(*(uint16_t *) (buf + 2))) @@ -838,17 +834,8 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) LOG(3, 0, 0, "Received DAE %s, id %d\n", radius_code(r_code), r_id); // check authenticator - memcpy(vector, buf + 4, 16); - memset(buf + 4, 0, 16); - - i = strlen(config->radiussecret); - if (i > 16) i = 16; - - MD5Init(&ctx); - MD5Update(&ctx, buf, len); - MD5Update(&ctx, buf, config->radiussecret, i); - MD5Final(hash, &ctx); - if (memcmp(hash, vector, 16) != 0) + calc_auth(buf, len, zero, hash); + if (memcmp(hash, buf + 4, 16) != 0) { LOG(1, 0, 0, "Incorrect vector in DAE request (wrong secret in radius config?)\n"); return; @@ -915,7 +902,7 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) } len = p - packet; - i = find_filter(packet, len); + i = find_filter((char *) packet, len); if (i < 0 || !*ip_filters[i].name) { error = 404; @@ -1027,20 +1014,17 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) } // apply filters - if (fin != -1 || fout != -1) - { - if (fin == -1) - fin = 0; - else - LOG(3, s, t, " Filter in %d (%s)\n", fin, ip_filters[fin - 1].name); + if (fin == -1) + fin = 0; + else + LOG(3, s, t, " Filter in %d (%s)\n", fin, ip_filters[fin - 1].name); - if (fout == -1) - fout = 0; - else - LOG(3, s, t, " Filter out %d (%s)\n", fout, ip_filters[fout - 1].name); + if (fout == -1) + fout = 0; + else + LOG(3, s, t, " Filter out %d (%s)\n", fout, ip_filters[fout - 1].name); - filter_session(s, fin, fout); - } + filter_session(s, fin, fout); // process cisco av-pair(s) for (i = 0; i < avp; i++) @@ -1057,10 +1041,9 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) packet = buf; *packet++ = r_code; *packet++ = r_id; - packet += 2; - memset(packet, 0, 16); - packet += 16; - len = 20; + // skip len + auth + packet += 2 + 16; + len = packet - buf; // add attributes if (error) @@ -1075,14 +1058,7 @@ void processdae(uint8_t *buf, int len, struct sockaddr_in *addr, int alen) *((uint16_t *)(buf + 2)) = htons(len); // make vector - i = strlen(config->radiussecret); - if (i > 16) i = 16; - - MD5Init(&ctx); - MD5Update(&ctx, buf, len); - MD5Update(&ctx, config->radiussecret, i); - MD5Final(hash, &ctx); - memcpy(buf + 4, hash, 16); + calc_auth(buf, len, hash, buf + 4); LOG(3, 0, 0, "Sending DAE %s, id=%d\n", radius_code(r_code), r_id);