Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 678423 Details for
Bug 648217
Enhancement request: Add EAP-PEAP support for RADIUS plugin
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
RADIUS EAP-TLS/EAP-TTLS Patch
ppp-2.4.5-radius-eaptls.patch (text/plain), 64.72 KB, created by
Michal Bruncko
on 2013-01-14 20:30:29 UTC
(
hide
)
Description:
RADIUS EAP-TLS/EAP-TTLS Patch
Filename:
MIME Type:
Creator:
Michal Bruncko
Created:
2013-01-14 20:30:29 UTC
Size:
64.72 KB
patch
obsolete
>diff -Nu ppp-2.4.5-orig/pppd/auth.c ppp-wegener-despace-stripnum/pppd/auth.c >--- ppp-2.4.5-orig/pppd/auth.c 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/auth.c 2013-01-14 18:11:15.949533401 +0100 >@@ -183,6 +185,9 @@ > /* Hook for a plugin to get the CHAP password for authenticating us */ > int (*chap_passwd_hook) __P((char *user, char *passwd)) = NULL; > >+/* Hook for a plugin to authenticate a peer with EAP TLS */ >+int (*eaptls_auth_hook) __P((char *peerName, int peerNameLen, char *eapTLSContent, int *contentLen)); >+ > /* Hook for a plugin to say whether it is OK if the peer > refuses to authenticate. */ > int (*null_auth_hook) __P((struct wordlist **paddrs, >@@ -231,6 +238,8 @@ > bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */ > bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */ > #endif >+bool stripnumber = 0; /* Strip phone number from username before making a wtmp record */ >+bool despaceflg = 0; /* Collapse spaces in username before making wtmp entry */ > bool usehostname = 0; /* Use hostname for our_name */ > bool auth_required = 0; /* Always require authentication from peer */ > bool allow_any_ip = 0; /* Allow peer to use any IP address */ >@@ -248,6 +257,10 @@ > static void network_phase __P((int)); > static void check_idle __P((void *)); > static void connect_time_expired __P((void *)); >+static char *stripnum __P((char *)); >+static char *despace __P((char *)); >+static int plogin __P((char *, char *, char **)); >+static void plogout __P((void)); > static int null_login __P((int)); > static int get_pap_passwd __P((char *)); > static int have_pap_secret __P((int *)); >@@ -383,6 +396,12 @@ > { "enable-session", o_bool, &session_mgmt, > "Enable session accounting for remote peers", OPT_PRIV | 1 }, > >+ { "stripnumber", o_bool, &stripnumber, >+ "Strip phone number in login wtmp record", 1 }, >+ >+ { "despace", o_bool, &despaceflg, >+ "Collapse spaces passed in login wtmp record", 1}, >+ > { "papcrypt", o_bool, &cryptpap, > "PAP passwords are encrypted", 1 }, > >diff -Nu ppp-2.4.5-orig/pppd/eap.c ppp-wegener-despace-stripnum/pppd/eap.c >--- ppp-2.4.5-orig/pppd/eap.c 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/eap.c 2007-12-03 08:59:21.000000000 +0100 >@@ -41,6 +41,9 @@ > * authenticator-driven protocol. > * > * Based on draft-ietf-pppext-eap-srp-03.txt. >+ * >+ * EAP TLS support by: >+ * michael.heiart@freenet.de > */ > > #define RCSID "$Id: eap.c,v 1.4 2004/11/09 22:39:25 paulus Exp $" >@@ -443,6 +447,14 @@ > return; > > case eapIdentify: >+ /* If we have an eaptls_auth_hook let remote peer and RADIUS server >+ negotiate how to authenticate (Exchange EAP messages). >+ Otherwise let pppd code handle the authentication */ >+ if(eaptls_auth_hook != NULL){ >+ esp->es_server.ea_state = eapTLSAuth; >+ break; >+ } >+ > #ifdef USE_SRP > /* Discard any previous session. */ > ts = (struct t_server *)esp->es_server.ea_session; >@@ -624,6 +636,14 @@ > } > break; > >+ case eapTLSAuth: >+ if (status != 0) { >+ esp->es_server.ea_state = eapBadAuth; >+ } else { >+ esp->es_server.ea_state = eapOpen; >+ } >+ break; >+ > default: > esp->es_server.ea_state = eapBadAuth; > break; >@@ -646,6 +666,14 @@ > int outlen; > int challen; > char *str; >+ int result; >+ char decapsulated_eaptls[2048]; >+ int eaptls_len; >+ >+ lenloc = NULL; >+ result = 0; >+ eaptls_len = 0; >+ > #ifdef USE_SRP > struct t_server *ts; > u_char clear[8], cipher[8], dig[SHA_DIGESTSIZE], *optr, *cp; >@@ -681,13 +709,16 @@ > } > > outp = outpacket_buf; >- >+ > MAKEHEADER(outp, PPP_EAP); > >- PUTCHAR(EAP_REQUEST, outp); >- PUTCHAR(esp->es_server.ea_id, outp); >- lenloc = outp; >- INCPTR(2, outp); >+ /* no indenting if pppd is proxy for eap tls */ >+ if(esp->es_server.ea_state != eapTLSAuth){ >+ PUTCHAR(EAP_REQUEST, outp); >+ PUTCHAR(esp->es_server.ea_id, outp); >+ lenloc = outp; >+ INCPTR(2, outp); >+ } > > switch (esp->es_server.ea_state) { > case eapIdentify: >@@ -698,6 +729,39 @@ > INCPTR(challen, outp); > break; > >+ case eapTLSAuth: >+ if(eaptls_auth_hook != NULL){ >+ result = eaptls_auth_hook(esp->es_server.ea_peer, >+ esp->es_server.ea_peerlen, >+ decapsulated_eaptls, >+ &eaptls_len); >+ >+ /* Decapsulate the attributes and move on >+ or inform the client that access is granted or >+ denied. If an error occors on the RADIUS Server side >+ (code 4) the client will only see that the access was denied */ >+ if((result != 0) || (decapsulated_eaptls[0] == 2) || (decapsulated_eaptls[0] == 4)) >+ { >+ eap_send_failure(esp); >+ return; >+ }else{ >+ str = decapsulated_eaptls; >+ challen = eaptls_len; >+ BCOPY(str, outp, challen); >+ INCPTR(challen, outp); >+ >+ if(decapsulated_eaptls[0] == 3){ >+ eap_send_success(esp); >+ } >+ } >+ }else{ >+ error("EAP TLS: No eaptls_auth_hook found!"); >+ eap_send_failure(esp); >+ return; >+ } >+ >+ break; >+ > case eapMD5Chall: > PUTCHAR(EAPT_MD5CHAP, outp); > /* >@@ -854,7 +918,11 @@ > } > > outlen = (outp - outpacket_buf) - PPP_HDRLEN; >- PUTSHORT(outlen, lenloc); >+ /* eapTlsContent already contains its length >+ for other authentication methods the length must be set */ >+ if(esp->es_server.ea_state != eapTLSAuth){ >+ PUTSHORT(outlen, lenloc); >+ } > > output(esp->es_unit, outpacket_buf, outlen + PPP_HDRLEN); > >@@ -1754,6 +1822,12 @@ > len--; > > switch (typenum) { >+ case EAPT_TLS: >+ case EAPT_TTLS: >+ /* use a Radius Server to authenticate this peer with EAP TLS */ >+ esp->es_server.ea_state = eapTLSAuth; >+ break; >+ > case EAPT_IDENTITY: > if (esp->es_server.ea_state != eapIdentify) { > dbglog("EAP discarding unwanted Identify \"%.q\"", len, >@@ -1761,6 +1835,7 @@ > break; > } > info("EAP: unauthenticated peer name \"%.*q\"", len, inp); >+ > if (esp->es_server.ea_peer != NULL && > esp->es_server.ea_peer != remote_name) > free(esp->es_server.ea_peer); >@@ -1797,7 +1872,16 @@ > } > > switch (vallen) { >- case EAPT_SRP: >+ case EAPT_TLS: >+ esp->es_server.ea_state = eapTLSAuth; >+ break; >+ >+ case EAPT_SRP: /* now EAP-SRP is suupported by radius too */ >+ if(eaptls_auth_hook != NULL) { >+ esp->es_server.ea_state = eapTLSAuth; >+ break; >+ } >+ > /* Run through SRP validator selection again. */ > esp->es_server.ea_state = eapIdentify; > eap_figure_next_state(esp, 0); >@@ -1890,6 +1974,11 @@ > > #ifdef USE_SRP > case EAPT_SRP: >+ if(eaptls_auth_hook != NULL) { /* now radius supports SRP too */ >+ esp->es_server.ea_state = eapTLSAuth; >+ break; >+ } >+ > if (len < 1) { > error("EAP: empty SRP Response"); > eap_figure_next_state(esp, 1); >diff -Nu ppp-2.4.5-orig/pppd/eap.h ppp-wegener-despace-stripnum/pppd/eap.h >--- ppp-2.4.5-orig/pppd/eap.h 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/eap.h 2007-04-26 11:33:12.000000000 +0200 >@@ -59,6 +59,7 @@ > #define EAPT_NOKIACARD 18 /* Nokia IP smart card */ > #define EAPT_SRP 19 /* Secure Remote Password */ > /* 20 is deprecated */ >+#define EAPT_TTLS 21 /* Tunnelles TLS */ > > /* EAP SRP-SHA1 Subtypes */ > #define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */ >@@ -88,6 +89,7 @@ > eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */ > eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */ > eapMD5Chall, /* Sent MD5-Challenge */ >+ eapTLSAuth, /* Work as proxy for EAP TLS */ > eapOpen, /* Completed authentication */ > eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */ > eapBadAuth /* Failed authentication */ >@@ -95,7 +97,7 @@ > > #define EAP_STATES \ > "Initial", "Pending", "Closed", "Listen", "Identify", \ >- "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth" >+ "SRP1", "SRP2", "SRP3", "MD5Chall", "TLSChall", "Open", "SRP4", "BadAuth" > > #define eap_client_active(esp) ((esp)->es_client.ea_state == eapListen) > #define eap_server_active(esp) \ >diff -Nu ppp-2.4.5-orig/pppd/pppd.h ppp-wegener-despace-stripnum/pppd/pppd.h >--- ppp-2.4.5-orig/pppd/pppd.h 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/pppd.h 2005-04-12 18:55:55.000000000 +0200 >@@ -80,6 +80,7 @@ > #define MAXARGS 1 /* max # args to a command */ > #define MAXNAMELEN 256 /* max length of hostname or name for auth */ > #define MAXSECRETLEN 256 /* max length of password or secret */ >+#define MAXEAPTLSLEN 2048 /* max length of eap tls content */ > > /* > * Option descriptor structure. >@@ -717,6 +715,8 @@ > extern int (*chap_passwd_hook) __P((char *user, char *passwd)); > extern void (*multilink_join_hook) __P((void)); > >+extern int (*eaptls_auth_hook) __P((char *peerName, int peerNameLen, char *eapTLSContent, int *contentLen)); >+ > /* Let a plugin snoop sent and received packets. Useful for L2TP */ > extern void (*snoop_recv_hook) __P((unsigned char *p, int len)); > extern void (*snoop_send_hook) __P((unsigned char *p, int len)); > >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary >--- ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary 2005-04-06 14:23:07.000000000 +0200 >@@ -87,6 +87,9 @@ > ATTRIBUTE Port-Limit 62 integer > ATTRIBUTE Connect-Info 77 string > >+ATTRIBUTE EAP-Message 79 string >+ATTRIBUTE EAP-Message-Authenticator 80 string >+ > # RFC 2869 > ATTRIBUTE Acct-Interim-Interval 85 integer > >@@ -251,3 +254,5 @@ > VALUE Octets-Direction MaxSession 4 > > INCLUDE /etc/radiusclient/dictionary.microsoft >+INCLUDE /etc/radiusclient/dictionary.cisco >+INCLUDE /etc/radiusclient/dictionary.siemens >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary.cisco ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary.cisco >--- ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary.cisco 1970-01-01 01:00:00.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary.cisco 2005-04-06 14:23:07.000000000 +0200 >@@ -0,0 +1,13 @@ >+# >+# Siemens dictionary for X.509 certificate attributes >+# >+# >+# Version: 1.00 18-Mar-2005 Michael Heiart >+# >+ >+VENDOR Cisco 9 >+ >+BEGIN-VENDOR Cisco >+# we need this to emulate a cisco ap with our pppd >+ATTRIBUTE Cisco-AVPair 1 string Cisco >+END-VENDOR Cisco >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary.siemens ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary.siemens >--- ppp-2.4.5-orig/pppd/plugins/radius/etc/dictionary.siemens 1970-01-01 01:00:00.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/etc/dictionary.siemens 2005-04-06 14:23:07.000000000 +0200 >@@ -0,0 +1,34 @@ >+# >+# Siemens dictionary for X.509 certificate attributes >+# >+# >+# Version: 1.00 04-Apr-2005 Michael Joosten >+# >+ >+VENDOR Siemens 4329 >+ >+BEGIN-VENDOR Siemens >+# general X509 subject/issuer attributes >+ >+ATTRIBUTE UserCert-CN 221 string Siemens >+ATTRIBUTE UserCert-SN 222 string Siemens >+ATTRIBUTE UserCert-GN 223 string Siemens >+ATTRIBUTE UserCert-O 224 string Siemens >+ATTRIBUTE UserCert-OU 225 string Siemens >+ATTRIBUTE UserCert-ST 226 string Siemens >+ATTRIBUTE UserCert-L 227 string Siemens >+ATTRIBUTE UserCert-Title 228 string Siemens >+ATTRIBUTE UserCert-Desc 229 string Siemens >+ATTRIBUTE UserCert-Name 230 string Siemens >+ATTRIBUTE UserCert-Initials 231 string Siemens >+ATTRIBUTE UserCert-Pseudonym 232 string Siemens >+ATTRIBUTE UserCert-Role 233 string Siemens >+ >+# some X509v3 extension attributes >+ATTRIBUTE UserCert-UPN 240 string Siemens >+ATTRIBUTE UserCert-URI 241 string Siemens >+ATTRIBUTE UserCert-DNS 242 string Siemens >+ATTRIBUTE UserCert-Email 243 string Siemens >+ATTRIBUTE UserCert-TCGID 244 string Siemens >+ >+END-VENDOR Siemens >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/Makefile.linux ppp-wegener-despace-stripnum/pppd/plugins/radius/Makefile.linux >--- ppp-2.4.5-orig/pppd/plugins/radius/Makefile.linux 2013-01-14 11:19:30.552418072 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/Makefile.linux 2013-01-14 17:41:10.211411163 +0100 >@@ -21,6 +21,9 @@ > MPPE=y > # Uncomment the next lint to include support for traffic limiting > MAXOCTETS=y >+# Uncomment the next lint to include support EAP TLS >+EAPTLS=y >+ > > ifdef CHAPMS > CFLAGS += -DCHAPMS=1 >@@ -31,6 +34,10 @@ > ifdef MAXOCTETS > CFLAGS += -DMAXOCTETS=1 > endif >+ifdef EAPTLS >+CFLAGS += -DEAPTLS=1 >+endif >+ > > all: $(PLUGIN) > >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/radius.c ppp-wegener-despace-stripnum/pppd/plugins/radius/radius.c >--- ppp-2.4.5-orig/pppd/plugins/radius/radius.c 2013-01-14 17:51:22.891407936 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/radius.c 2013-01-14 17:57:08.109408578 +0100 >@@ -19,6 +19,13 @@ > * MPPE support is by Ralf Hofmann, <ralf.hofmann@elvido.net>, with > * modification from Frank Cusack, <frank@google.com>. > * >+* EAP TLS support by: >+* Michael Heiart, <michael.heiart@freenet.de> and >+* Michael Joosten, <michael.joosten@c-lab.de> >+* >+* Sync pppd with new radiusclient lib by: >+* Dirk Nehring, <dnehring@marcant.net>* >+* > * This plugin may be distributed according to the terms of the GNU > * General Public License, version 2 or (at your option) any later version. > * >@@ -35,6 +42,7 @@ > #endif > #endif > #include "radiusclient.h" >+#include "eap.h" > #include "fsm.h" > #include "ipcp.h" > #include <syslog.h> >@@ -45,6 +53,13 @@ > #include <stdlib.h> > > #define BUF_LEN 1024 >+#include <sys/socket.h> >+#include <netinet/in.h> >+#include <arpa/inet.h> >+ >+#include <sys/types.h> >+#include <unistd.h> >+#include <sys/stat.h> > > #define MD5_HASH_SIZE 16 > >@@ -78,6 +93,20 @@ > unsigned char *response, > char *message, int message_space); > >+static int radius_eaptls(char *peername, >+ int peernameLen, >+ char *eapTLSContent, >+ int *contentLen); >+ >+static void radius_snoop_received(unsigned char *pppPacket, int len); >+ >+static int radius_get_free_ip(); >+static int radius_release_ip(); >+static int check_stale_pool_blocking(); >+ >+static int log_addr_user(char* ip_addr, char* user); >+int clear_log_byaddr(char* ip_addr); >+ > static void radius_ip_up(void *opaque, int arg); > static void radius_ip_down(void *opaque, int arg); > static void make_username_realm(char *user); >@@ -122,6 +151,14 @@ > int class_len; > char class[MAXCLASSLEN]; > VALUE_PAIR *avp; /* Additional (user supplied) vp's to send to server */ >+ unsigned char *ppp_snoop_data; >+ int ppp_snoop_len; >+ int state_attr_len; >+ char state_attr[512]; >+ char radius_cert_UPN[256]; >+ char radius_cert_CN[256]; >+ char radius_cert_TCGID[256]; >+ char radius_acct_username[128]; > }; > > void (*radius_attributes_hook)(VALUE_PAIR *) = NULL; >@@ -136,6 +173,23 @@ > > char pppd_version[] = VERSION; > >+/* the ip pool file (for the common ippool) */ >+static char ippoolfile[]="/etc/ppp/base.ippool"; >+ >+/* the ippool for a specific usergroup which uses its own pool */ >+static char usergroup[128]; >+char usergroup_dir[128]; /* for logging of user groups */ >+ >+/* 0 = NO EAP-Message-Authenticator needed. 1 = Needed */ >+int eap_tls_flag = 0; >+ >+/* 0= do not use the ip pool, 1 = set peers IP by Framed-IP-Address attribute */ >+int ip_pool_flag = 0; >+ >+/* extracted data from RADIUS user certificate attributes >+ * (requires FreeRadius patch) >+ */ >+ > /********************************************************************** > * %FUNCTION: plugin_init > * %ARGUMENTS: >@@ -148,12 +202,24 @@ > void > plugin_init(void) > { >+ /* file pointer for all initialisations */ >+ FILE *pFile; >+ > pap_check_hook = radius_secret_check; > pap_auth_hook = radius_pap_auth; > > chap_check_hook = radius_secret_check; > chap_verify_hook = radius_chap_verify; > >+#ifdef EAPTLS >+ info("Using EAP TLS."); >+ eaptls_auth_hook = radius_eaptls; >+#else >+ eaptls_auth_hook = NULL; >+#endif >+ >+ snoop_recv_hook = radius_snoop_received; >+ > ip_choose_hook = radius_choose_ip; > allowed_address_hook = radius_allowed_address; > >@@ -167,6 +233,31 @@ > > add_options(Options); > >+ eap_tls_flag = 0; >+ ip_pool_flag = 0; >+ >+ rstate.radius_cert_UPN[0]='\0'; >+ rstate.radius_cert_CN[0]='\0'; >+ rstate.radius_cert_TCGID[0]='\0'; >+ >+ /* open the ip pool file */ >+ /* start with the common ip pool under etc/ppp/ippool.txt */ >+ strcpy(usergroup,ippoolfile); >+ pFile = fopen(usergroup,"r+"); >+ >+ if(pFile == NULL) >+ { >+ error("No IP pool file found!"); >+ error("Will use default IP declared in ppp/options instead for clients"); >+ ip_pool_flag = 0; >+ }else{ >+ fclose(pFile); >+ ip_pool_flag = 1; >+ dbglog("ppp IP pool set to enabled!"); >+ } >+ >+ rstate.state_attr_len = 0; >+ > info("RADIUS plugin initialized."); > } > >@@ -300,16 +391,45 @@ > } > > if (result == OK_RC) { >+ dbglog("PAP authentication sucessful"); > if (radius_setparams(received, radius_msg, NULL, NULL, NULL, NULL, 0) < 0) { > result = ERROR_RC; > } >+ } else { >+ warn("PAP authentication failed, result: %d",result); > } > > /* free value pairs */ > rc_avpair_free(received); > rc_avpair_free(send); > >- return (result == OK_RC) ? 1 : 0; >+ if(result == OK_RC){ >+ >+ /* If the authentication succeeded, >+ * take an IP from the pool if the pool >+ * is available */ >+ >+ if(ip_pool_flag) { >+ rstate.choose_ip = 1; >+ result = radius_get_free_ip(); >+ /* found a free ip address */ >+ if(result == 0){ >+ dbglog("PAP: ---> Using local IP pool"); >+ } else { >+ /* no ip address is free/ available */ >+ error("PAP: ---> Can NOT use local IP pool. All IPs are in use already!"); >+ /* force to use 255.255.255.255 >+ this will make both xp and >+ linux clients terminate the ppp connection */ >+ rstate.ip_addr = -1; >+ } >+ } >+ >+ return 2; /* this means UPAP_AUTHACK in auth.c / user authenticated successfully by RADIUS server */ >+ >+ } else { >+ return 3; /* this means UPAP_AUTHNAK in auth.c / user rejected by RADIUS server */ >+ } > } > > /********************************************************************** >@@ -483,10 +612,29 @@ > rstate.done_chap_once = 1; > } > } >+ >+ if (ip_pool_flag == 1) { >+ rstate.choose_ip = 1; >+ /* usergroup already set in radius_setparams() */ >+ result = radius_get_free_ip(); >+ /* found a free ip address? */ >+ if (result == 0) { >+ dbglog("CHAP: ---> Using local IP pool"); >+ } else { >+ /* no ip address is free or available */ >+ error("CHAP: ---> Can NOT use local IP pool. All IPs are in use already!"); >+ /* force to use 255.255.255.255 >+ this will make both xp and >+ linux clients exit immediately */ >+ rstate.ip_addr = -1; >+ } >+ } > } > >+ /* free value pairs */ > rc_avpair_free(received); > rc_avpair_free (send); >+ > return (result == OK_RC); > } > >@@ -543,6 +691,12 @@ > int mppe_enc_policy = 0; > int mppe_enc_types = 0; > #endif >+ char name[128]; >+ char value [128]; >+ >+ /* CISCO proprietary attrs for DNS and WINS */ >+ char *cisco_ip_str, *cisco_end_ip_str; >+ unsigned long int ip = 0; > > /* Send RADIUS attributes to anyone else who might be interested */ > if (radius_attributes_hook) { >@@ -554,8 +708,20 @@ > * new IP address (RADIUS can define static IP for some users), > */ > >- while (vp) { >- if (vp->vendorcode == VENDOR_NONE) { >+ while(vp) >+ { >+ if (debug) >+ { >+ /* print returned attributes */ >+ if (rc_avpair_tostr(vp, name, sizeof(name), value, sizeof(value)) >= 0) >+ { >+ dbglog("Vendor '%d' Attr '%s', Code '%d' ==> Val '%s'\n", vp->vendorcode, >+ name, vp->attribute, value); >+ } >+ } >+ >+ if (vp->vendorcode == VENDOR_NONE) >+ { > switch (vp->attribute) { > case PW_SERVICE_TYPE: > /* check for service type */ >@@ -781,10 +781,14 @@ > remote, rstate.user); > return -1; > } >+ dbglog("Received a Framed-IP from RADIUS. Disabling ippool..."); >+ ip_pool_flag = 0; >+ > rstate.choose_ip = 1; > rstate.ip_addr = remote; > } > break; >+ > case PW_CLASS: > /* Save Class attribute to pass it in accounting request */ > if (vp->lvalue <= MAXCLASSLEN) { >@@ -792,11 +796,83 @@ > memcpy(rstate.class, vp->strvalue, rstate.class_len); > } /* else too big for our buffer - ignore it */ > break; >+ >+ /* internal Radius server attribute */ >+ case PW_STATE: >+ /* preserve the RADIUS state between requests! */ >+ if (vp->lvalue <= sizeof(rstate.state_attr)) { >+ rstate.state_attr_len = vp->lvalue; >+ memcpy(rstate.state_attr, vp->strvalue, rstate.state_attr_len); >+ } >+ break; >+ } >+ >+ }else if(vp->vendorcode == VENDOR_CISCO) { >+ if (vp->attribute == PW_CISCO_AVPAIR) { >+ /* emulate what a CISCO AP would do (more or less) */ >+ if(strstr(vp->strvalue, "ip:dns-servers=") != NULL) { >+ cisco_ip_str = vp->strvalue + sizeof("ip:dns-servers=")-1; >+ >+ /* mult. entries separated by ' ' only */ >+ cisco_end_ip_str = strchr(cisco_ip_str, ' '); >+ if (cisco_end_ip_str == NULL) { >+ dbglog("Cisco DNS server attribute: %s", cisco_ip_str); >+ ip = inet_addr(cisco_ip_str); >+ ipcp_allowoptions[0].dnsaddr[0] = ip; >+ ipcp_allowoptions[0].dnsaddr[1] = ip; >+ } else { >+ /* we got a space, so extract two dotted IP addresses */ >+ *cisco_end_ip_str++ = '\0'; >+ dbglog("Cisco DNS1 server attribute: %s", cisco_ip_str); >+ ip = inet_addr(cisco_ip_str); >+ ipcp_allowoptions[0].dnsaddr[0] = ip; >+ dbglog("Cisco DNS2 server attribute: %s", cisco_end_ip_str); >+ ip = inet_addr(cisco_end_ip_str); >+ ipcp_allowoptions[0].dnsaddr[1] = ip; >+ } >+ } >+ >+ if(strstr(vp->strvalue, "ip:wins-servers=") != NULL){ >+ cisco_ip_str = vp->strvalue + sizeof("ip:wins-servers=")-1; >+ >+ /* mult. entries separated by ' ' only */ >+ cisco_end_ip_str = strchr(cisco_ip_str, ' '); >+ if (cisco_end_ip_str == NULL) { >+ dbglog("Cisco WINS server attribute: %s", cisco_ip_str); >+ ip = inet_addr(cisco_ip_str); >+ ipcp_allowoptions[0].winsaddr[0] = ip; >+ ipcp_allowoptions[0].winsaddr[1] = ip; >+ } else { >+ /* we got a space, so extract two dotted IP addresses */ >+ *cisco_end_ip_str++ = '\0'; >+ dbglog("Cisco WINS1 server attribute: %s", cisco_ip_str); >+ ip = inet_addr(cisco_ip_str); >+ ipcp_allowoptions[0].winsaddr[0] = ip; >+ dbglog("Cisco WINS2 server attribute: %s", cisco_end_ip_str); >+ ip = inet_addr(cisco_end_ip_str); >+ ipcp_allowoptions[0].winsaddr[1] = ip; >+ } >+ } >+ >+ if(strstr(vp->strvalue, "ip:addr-pool=") != NULL){ >+ ip_pool_flag = 1; >+ >+ /* change usergroup if RADIUS server sends a ippool name */ >+ if(strstr(vp->strvalue, "../") != NULL){ >+ info("Found CISCO addr-pool with illegal '../' sequence."); >+ info("Omitting this value pair."); >+ }else{ >+ slprintf(usergroup, sizeof(usergroup), "%s%s%s", "/etc/ppp/", >+ vp->strvalue +sizeof("ip:addr-pool=")-1, ".ippool"); >+ dbglog("Usergroup for this user is: '%s'", usergroup); >+ } >+ } > } >+ } /*End of vendor CISCO */ > > > #ifdef CHAPMS >- } else if (vp->vendorcode == VENDOR_MICROSOFT) { >+ else if (vp->vendorcode == VENDOR_MICROSOFT) { > switch (vp->attribute) { > case PW_MS_CHAP2_SUCCESS: > if ((vp->lvalue != 43) || strncmp(vp->strvalue + 1, "S=", 2)) { >@@ -673,13 +914,23 @@ > break; > > #endif /* MPPE */ >-#if 0 >+ > case PW_MS_PRIMARY_DNS_SERVER: >+ ipcp_allowoptions[0].dnsaddr[0] = ntohl(vp->lvalue); >+ break; >+ > case PW_MS_SECONDARY_DNS_SERVER: >+ ipcp_allowoptions[0].dnsaddr[1] = ntohl(vp->lvalue); >+ break; >+ > case PW_MS_PRIMARY_NBNS_SERVER: >+ ipcp_allowoptions[0].winsaddr[0] = ntohl(vp->lvalue); >+ break; >+ > case PW_MS_SECONDARY_NBNS_SERVER: >+ ipcp_allowoptions[0].winsaddr[1] = ntohl(vp->lvalue); > break; >-#endif >+ > } > #endif /* CHAPMS */ > } >@@ -1178,6 +1439,18 @@ > static void > radius_ip_up(void *opaque, int arg) > { >+ if(ip_pool_flag == 1){ >+ /* log IP and userName into file */ >+ unsigned long int ip; >+ struct in_addr ip32; >+ int logOk = -1; >+ >+ ip = rstate.ip_addr; >+ ip32.s_addr = ip; >+ >+ logOk = log_addr_user(inet_ntoa(ip32), rstate.user); >+ } >+ > radius_acct_start(); > } > >@@ -1194,6 +1467,22 @@ > static void > radius_ip_down(void *opaque, int arg) > { >+ unsigned long int ip; >+ struct in_addr ip32; >+ >+ /* if the pool is in use we can release an IP address from the list */ >+ if(ip_pool_flag == 1 && rstate.ip_addr != -1) >+ { >+ if(radius_release_ip() != 0) >+ { >+ error("Could not release IP Address from pool!"); >+ } >+ /* we should always try to erase the log for this IP address */ >+ ip = rstate.ip_addr; >+ ip32.s_addr = ip; >+ clear_log_byaddr(inet_ntoa(ip32)); >+ } >+ > radius_acct_stop(); > } > >@@ -1304,3 +1593,813 @@ > { > return rstate.user; > } >+ >+/********************************************************************** >+* %FUNCTION: radius_eaptls >+* Performs EAP TLS authentications with >+* a RADIUS Server. >+* %ARGUMENTS: >+* peername -- username(identity) of remote peer >+* peername_len -- length of username(identity) of remote peer >+* peername -- username(identity) of remote peer >+* eaptls_content -- the buffer to return the eap tls messages received from RADIUS server >+* content_len -- the length of the eap tls content received from the RADIUS server >+* %RETURNS: >+* 0 if it was possible to communcate with the RADIUS server; >+* 1 if problems occured during communication with RADIUS server >+***********************************************************************/ >+static int >+radius_eaptls(char *peername, int peername_len, char *eaptls_content, int *content_len) >+{ >+ VALUE_PAIR *send, *received, *avpairs; >+ int result; >+ static char radius_msg[BUF_LEN]; >+ int type = 0; >+ int contentSize = 0; >+ >+#ifdef MPPE >+ /* Need the RADIUS secret and Request Authenticator to decode MPPE */ >+ REQUEST_INFO request_info, *req_info = &request_info; >+#else >+ REQUEST_INFO *req_info = NULL; >+#endif >+ >+ memcpy(rstate.user, peername, peername_len); >+ rstate.user[peername_len] = 0; >+ >+ radius_msg[0] = 0; >+ >+ if (radius_init(radius_msg) < 0) { >+ return 0; >+ } >+ >+ if (radius_pre_auth_hook) { >+ radius_pre_auth_hook(rstate.user, >+ &rstate.authserver, >+ &rstate.acctserver); >+ } >+ >+ send = NULL; >+ received = NULL; >+ >+ /* Hack... the "port" is the ppp interface number. >+ * Should really be the tty */ >+ rstate.client_port = get_client_port(portnummap ? devnam : ifname); >+ >+ /* Add User-Name attribute */ >+ type = PW_USER_NAME; >+ rc_avpair_add(&send, type, rstate.user, strlen(rstate.user)+1, VENDOR_NONE); >+ >+ /* Add EAP Message attribute with previously received EAP packet from peer */ >+ /* Maximum length of an eap message is 255 (type + length + String) */ >+ /* Therefore a length of 253 = EAP_TLS_MAX_STRING_LEN is left for our chunk */ >+ type = PW_EAP_MESSAGE; >+ if (rstate.ppp_snoop_len-4 <= EAP_TLS_MAX_STRING_LEN) { >+ rc_avpair_add(&send, type, rstate.ppp_snoop_data+4, rstate.ppp_snoop_len-4, VENDOR_NONE); >+ } else { >+ /* write EAP frament in chunks of 253 bytes payload or the rest of payload left*/ >+ int written = 0; >+ int chunk = EAP_TLS_MAX_STRING_LEN; >+ while (written < rstate.ppp_snoop_len-4) { >+ rc_avpair_add(&send, type, rstate.ppp_snoop_data+4+written, chunk, VENDOR_NONE); >+ written += chunk; >+ if(rstate.ppp_snoop_len-4-written >= EAP_TLS_MAX_STRING_LEN){ >+ chunk = EAP_TLS_MAX_STRING_LEN; >+ }else{ >+ chunk = rstate.ppp_snoop_len-4-written; >+ } >+ } >+ } >+ >+ /* Add a state attribute >+ * The Radius server uses the state attribute to find the dataset >+ * belonging to an authentication process */ >+ if (rstate.state_attr_len > 0) { >+ type = PW_STATE; >+ rc_avpair_add(&send, type, rstate.state_attr, rstate.state_attr_len, VENDOR_NONE); >+ } >+ >+ /* Add user specified vp's */ >+ if (rstate.avp) >+ rc_avpair_insert(&send, NULL, rc_avpair_copy(rstate.avp)); >+ >+ /* Indicate that a Message Authenticator is necessary */ >+ eap_tls_flag = 1; >+ >+ if (rstate.authserver) { >+ result = rc_auth_using_server(rstate.authserver, >+ rstate.client_port, send, >+ &received, radius_msg, req_info); >+ } else { >+ result = rc_auth(rstate.client_port, send, &received, radius_msg, req_info); >+ } >+ >+ /* extract common attributes */ >+ if (result == OK_RC) { >+ if (radius_setparams(received, radius_msg, req_info, NULL, NULL, NULL, 0) < 0) { >+ result = ERROR_RC; >+ } >+ } >+ >+ /* Radius Client acts as proxy */ >+ /* decapsulate pure EAP that can be send to the peer */ >+ contentSize = 0; >+ >+ /* extract EAP/TLS specific attributes */ >+ avpairs = received; >+ for( ; received ; received = received->next) { >+ >+ /* X509 certificate specific attributes from FreeRadius */ >+ if (received->vendorcode == VENDOR_SIEMENS) { >+ switch(received->attribute){ >+ case PW_USERCERT_UPN: >+ strncpy(rstate.radius_cert_UPN, received->strvalue, sizeof(rstate.radius_cert_UPN)-1); >+ rstate.radius_cert_UPN[sizeof(rstate.radius_cert_UPN)-1] = '\0'; >+ break; >+ case PW_USERCERT_CN: >+ strncpy(rstate.radius_cert_CN, received->strvalue, sizeof(rstate.radius_cert_CN)-1); >+ rstate.radius_cert_CN[sizeof(rstate.radius_cert_CN)-1] = '\0'; >+ case PW_USERCERT_TCGID: >+ strncpy(rstate.radius_cert_TCGID, received->strvalue, sizeof(rstate.radius_cert_TCGID)-1); >+ rstate.radius_cert_TCGID[sizeof(rstate.radius_cert_TCGID)-1] = '\0'; >+ } >+ } >+ >+ if(received->attribute == PW_EAP_MESSAGE){ >+ /* does the Radius fragment still fit in to the EAP-TLS fragment buffer? */ >+ if (received->lvalue < EAP_TLS_MAX_BUFFER_LEN - contentSize){ >+ memcpy(&eaptls_content[contentSize], >+ received->strvalue,received->lvalue); >+ contentSize += received->lvalue; >+ } else { >+ error("too many Radius TLS fragments for EAP buffer!"); >+ result = ERROR_RC; >+ } >+ } >+ } >+ >+ /* reset avpair list */ >+ received = avpairs; >+ >+ /* free value pairs */ >+ rc_avpair_free(received); >+ rc_avpair_free(send); >+ >+ *content_len=contentSize; >+ >+ /* rc_auth() == OK_RC is NOT enough, we are >+ * not through all request/replies until.. */ >+ if(result == OK_RC && eaptls_content[0] == 3){ >+ >+ /* did we get an identity back from the server ?? */ >+ rstate.radius_acct_username[0] = '\0'; >+ >+ if(rstate.radius_cert_UPN[0] == '\0'){ >+ dbglog("RADIUS server did not return principalName!"); >+ result = ERROR_RC; >+ }else{ >+ dbglog("Extraction of principalName from RADIUS server succeeded!"); >+ strcpy(rstate.radius_acct_username, rstate.radius_cert_UPN); >+ } >+ >+ if(rstate.radius_acct_username[0] == '\0'){ >+ if(rstate.radius_cert_TCGID[0] == '\0'){ >+ error("RADIUS server did not return TCGID!"); >+ result = ERROR_RC; >+ }else{ >+ dbglog("Extraction of TCGID from RADIUS server succeeded!"); >+ strcpy(rstate.radius_acct_username, rstate.radius_cert_TCGID); >+ } >+ } >+ >+ if(rstate.radius_acct_username[0] == '\0'){ >+ if(rstate.radius_cert_CN[0] == '\0'){ >+ error("RADIUS server did not return commonName!"); >+ result = ERROR_RC; >+ }else{ >+ dbglog("Extraction of commonName from RADIUS succeeded!"); >+ strcpy(rstate.radius_acct_username, rstate.radius_cert_CN); >+ } >+ } >+ >+ if(rstate.radius_acct_username[0] == '\0'){ >+ strcat(rstate.user, "--NOT VERIFIED IN CERT!"); >+ }else{ >+ strcpy(rstate.user, rstate.radius_acct_username); >+ } >+ >+ dbglog("EAP TLS authentication succeeded for '%s'", rstate.user); >+ dbglog("This user will get an IP from the following ippool: '%s'", usergroup); >+ >+ /* If the ippool flag is set we use the pppd IP pool. */ >+ if (ip_pool_flag == 1) >+ { >+ /* ippool available and user belongs to trusted realm. >+ * If the user is not trusted failure is sent (see 10 lines above) */ >+ result = radius_get_free_ip(); >+ >+ /* found a free ip address */ >+ if (result == 0){ >+ rstate.choose_ip = 1; >+ dbglog("EAP TLS: ---> Using local IP pool"); >+ } else { /* no ip address is free/available */ >+ error("EAP TLS: ---> Can NOT use local IP pool. All IPs are in use already!"); >+ /* force to use 255.255.255.255 >+ this will make both xp and >+ linux clients exit immediately */ >+ rstate.ip_addr = -1; >+ } >+ } else { >+ result = OK_RC; >+ } >+ } >+ >+ if(result == OK_RC){ >+ return 0; >+ }else{ >+ return 1; >+ } >+} >+ >+/****************************************************************************************** >+ * Function: radius_snoop_received >+ * stores packets received by pppd >+ * in rstate for further use >+ ******************************************************************************************/ >+static void >+radius_snoop_received(unsigned char *p, int len) >+{ >+ rstate.ppp_snoop_data = p; >+ rstate.ppp_snoop_len = len; >+ >+} >+ >+/****************************************************************************************** >+ * Function: radius_get_free_ip() >+ * if the plugIn handles an ippool >+ * this function returns a >+ * free IP for the client >+ ******************************************************************************************/ >+static int radius_get_free_ip() >+{ >+ unsigned long int rangeStart = 0; >+ unsigned long int rangeEnd = 0; >+ >+ unsigned long int ip = 0; >+ unsigned long int ipLastInUse = 0; >+ int size = 16; >+ char dotted[16]; >+ struct in_addr ip32; >+ >+ FILE *pFile; >+ char line[256]; >+ short counter; >+ int seconds = 0; >+ int pid; >+ char pidStr[10]; >+ >+ int result; >+ >+ dbglog("============================== IP POOL =============================="); >+ >+ /* check if a stale process blocks the pool and unblock pool if necessary */ >+ result = check_stale_pool_blocking(); >+ if(result != 0){ >+ rstate.ip_addr = ip; >+ error("Error while unblocking IP pool!"); >+ } >+ >+ /* check if another process is working with the pool data at the moment */ >+ >+ /* open the ippool file */ >+ >+ pFile = fopen(usergroup,"r+"); >+ >+ if (pFile == NULL) >+ { >+ error("The IP pool file could not be found: '%s'", usergroup); >+ return -1; >+ } else { >+ fclose(pFile); >+ } >+ >+ pFile = fopen(usergroup,"r+"); >+ while (fgetc(pFile) == 'b' && seconds < 10) >+ { >+ /* another process uses the ippool file */ >+ dbglog("Another process blocks the IP pool...waiting...%d seconds", seconds); >+ sleep(1); >+ seconds++; >+ >+ fclose(pFile); >+ >+ pFile = fopen(usergroup,"r+"); >+ if(pFile == NULL){ >+ return -1; >+ } >+ } >+ >+ if(seconds > 8) >+ { >+ error("The IP pool was blocked by another process too long!!!"); >+ error("Can not assign addres at the moment!!!"); >+ return -1; >+ } >+ >+ /* block the pool now for this process */ >+ /* use process id to indicate which proc blocks */ >+ pid = getpid(); >+ dbglog("process blocking IP pool: %d", pid); >+ sprintf(pidStr, "%d", pid); >+ rewind(pFile); >+ fputc('b', pFile); >+ fputs(pidStr, pFile); >+ rewind(pFile); >+ >+ /* determin next free ip */ >+ >+ fgets(line,sizeof(line),pFile); >+ >+ while(line[0] != 'E') >+ { >+ char indicator = 0; >+ char intBuffer[4]; >+ long position; >+ >+ if((size = strlen(line)) == 0) >+ { >+ /* we do not expect empty lines */ >+ break; >+ } >+ >+ indicator = line[0]; >+ intBuffer[3] = 0; >+ size = strlen(line); >+ >+ switch(indicator){ >+ case 'b': >+ dbglog("IP pool blocked --> OK!"); >+ break; >+ >+ case 'f': >+ error("IP pool is not blocked but in use!!!"); >+ fclose(pFile); >+ return -1; >+ >+ case 's': >+ /* ip range start */ >+ strncpy(dotted,line+1,size); >+ dbglog("IP range start: %s", dotted); >+ ip = inet_addr(dotted); >+ ip32.s_addr = ip; >+ rangeStart = ip; >+ break; >+ >+ case 'e': >+ /* ip range end */ >+ strncpy(dotted,line+1,size); >+ dbglog("IP range end: %s", dotted); >+ ip = inet_addr(dotted); >+ ip32.s_addr = ip; >+ rangeEnd = ip; >+ break; >+ >+ case 'i': >+ /* ip address that IS in use */ >+ /* Remember last used ip for calculation of next new IP */ >+ strncpy(dotted,line+1,size); >+ ipLastInUse = inet_addr(dotted); >+ dbglog("SETTING LAST IN USE IP: %s", dotted); >+ break; >+ >+ case 'x': >+ /* this ip is free */ >+ /* use it for this client */ >+ >+ dbglog("Free old IP found.....will use it for this client."); >+ strncpy(dotted,line+1,size); >+ ip = inet_addr(dotted); >+ >+ /* write the ip in rstate */ >+ /* if rstate.choose_ip is set to 1 */ >+ /* this ip will be used in network phase */ >+ rstate.ip_addr = ip; >+ ip32.s_addr = ip; >+ dbglog("Client should use IP: %s", inet_ntoa(ip32)); >+ >+ rstate.choose_ip = 1; >+ >+ /* mark this ip as in use */ >+ size = strlen(dotted)+1; >+ position = ftell(pFile); >+ fseek(pFile, position-size, SEEK_SET); >+ fputc('i', pFile); >+ >+ /* unlock the pool for other process */ >+ rewind(pFile); >+ /* fputc('f', pFile); */ >+ for(counter = 0; counter < 10; counter++){ >+ fputc('f', pFile); >+ } >+ >+ fclose(pFile); >+ pFile = NULL; >+ >+/*nw*/ >+ char stoepselbuf[100]; >+ sprintf(stoepselbuf,"/usr/sbin/stoepsel %s v1\n",inet_ntoa(ip32)); >+ system("/bin/logger -t nwradius vor stoepsel"); >+ system(stoepselbuf); >+ system("/bin/logger -t nwradius nach stoepsel"); >+/*nw*/ >+ >+ return 0; >+ >+ case ' ': >+ error("Empty line in ippool file!"); >+ error("Pool remains looked!"); >+ error("Correct pool and set first character to f!"); >+ error("No need to kill PPP for this!"); >+ fclose(pFile); >+ pFile = NULL; >+ return -1; >+ >+ case '\n': >+ error("Empty line in ippool file!"); >+ error("Pool remains looked!"); >+ error("Correct pool and set first character to f!"); >+ error("No need to kill PPP for this!"); >+ fclose(pFile); >+ pFile = NULL; >+ return -1; >+ >+ default: >+ error("Unreadable entry in IP pool!!!"); >+ error("Pool remains looked!"); >+ error("Correct pool and set first character to f!"); >+ error("No need to kill PPP for this!"); >+ fclose(pFile); >+ pFile = NULL; >+ return -1; >+ } /* end switch */ >+ >+ /* get next line of file */ >+ fgets(line,sizeof(line),pFile); >+ >+ } /*end while */ >+ >+ /* if this code is reached we have to generate a new ip */ >+ >+ /* if this is still the range end */ >+ /* use the range start */ >+ if(ipLastInUse == 0){ >+ /* increase range start and you have the IP */ >+ ip = ntohl(rangeStart); >+ }else{ >+ /* increase the number of the last IP in use */ >+ ip = ntohl(ipLastInUse) + 1; >+ } >+ >+ /* perhaps all IPs are in use */ >+ if(ip > ntohl(rangeEnd)) >+ { >+ error("Can not assign ip. All IPs are in use!!!"); >+ /* unlock the pool for other process */ >+ >+ if(pFile == NULL){ >+ pFile = fopen(usergroup,"r+"); >+ } >+ rewind(pFile); >+ >+ /* unblock the ippool */ >+ for(counter = 0; counter < 10; counter++){ >+ fputc('f', pFile); >+ } >+ fclose(pFile); >+ >+ return -1; >+ } >+ >+ /* convert back to the network format */ >+ ip = htonl(ip); >+ >+ /* pool file still open? */ >+ if(pFile == NULL) >+ { >+ error("Can not append new IP. File is closed!"); >+ } >+ >+ /* store the ip the client should use in rstate and >+ mark rstate.choose_ip as active */ >+ rstate.ip_addr = ip; >+ ip32.s_addr = ip; >+ dbglog("Client should use IP: %s", inet_ntoa(ip32)); >+ rstate.choose_ip = 1; >+ >+ /* go to the end of the ip file */ >+ fseek(pFile, -4, SEEK_END); >+ >+ /* append the new IP */ >+ sprintf(line,"i%s\nEnd\n",inet_ntoa(ip32)); >+ fputs(line, pFile); >+ >+/*nw*/ >+ char stoepselbuf[100]; >+ sprintf(stoepselbuf,"/usr/sbin/stoepsel %s v1\n",inet_ntoa(ip32)); >+ system("/bin/logger -t nwradius vor stoepsel"); >+ system(stoepselbuf); >+ system("/bin/logger -t nwradius nach stoepsel"); >+/*nw*/ >+ >+ /* unlock the pool for other process */ >+ rewind(pFile); >+ fputc('f', pFile); >+ >+ /* close the file */ >+ if(pFile != NULL) >+ { >+ fclose(pFile); >+ } >+ >+ return 0; >+} >+ >+/***************************************************************************** >+ * Function: radius_release_ip() >+ * if the client stops the connection >+ * the IP should be marked as free >+ * for use with other client >+ *****************************************************************************/ >+static int radius_release_ip() >+{ >+ char line[256]; >+ char searchString[256]; >+ unsigned long int ip; >+ struct in_addr ip32; >+ int result; >+ FILE *pFile, *fopen(); >+ int seconds = 0; >+ int len; >+ long position; >+ >+ ip = rstate.ip_addr; >+ ip32.s_addr = ip; >+ sprintf(searchString,"%s%s\n", "i", inet_ntoa(ip32)); >+ dbglog("Trying to release IP: %s", searchString); >+ >+ /* check if a stale process blocks the pool and unblock pool if necessary */ >+ result = check_stale_pool_blocking(); >+ if(result != 0){ >+ dbglog("Error while unblocking IP pool!"); >+ } >+ >+ /* check if another process is working with the pool data at the moment */ >+ >+ /* open the ippool file */ >+ >+ pFile = fopen(usergroup,"r+"); >+ >+ if(pFile == NULL) >+ { >+ error("The IP pool file could not be found!"); >+ return -1; >+ }else{ >+ fclose(pFile); >+ } >+ >+ pFile = fopen(usergroup,"r+"); >+ while( fgetc(pFile) == 'b' && seconds < 10) >+ { >+ /* another process uses the ippool file */ >+ dbglog("Another process occupies IP pool...waiting...%d seconds", seconds); >+ >+ if(pFile == NULL){ >+ return -1; >+ } >+ >+ fclose(pFile); >+ sleep(1); >+ seconds++; >+ >+ /*rewind(pFile); --> does not work --> MUST reopen file */ >+ pFile = fopen(usergroup,"r+"); >+ } >+ >+ if(seconds > 8) >+ { >+ error("The IP pool was blocked by another process too long!!!"); >+ error("Can not release IP at the moment!!!"); >+ return -1; >+ } >+ >+ /* block the pool now for this process */ >+ pFile = fopen(usergroup,"r+"); >+ rewind(pFile); >+ fputs("b", pFile); >+ >+ /* find the line where rstate.ip_addr can be found */ >+ >+ fgets(line,256,pFile); >+ >+ while(line[0] != 'E') >+ { >+ if(strcmp(line,searchString) == 0) >+ { >+ dbglog("Found IP: %s in list. Trying release....", line); >+ /* mark this ip as free */ >+ position = ftell(pFile); >+ len = strlen(searchString); >+ position = position - len; >+ fseek(pFile, position, SEEK_SET); >+ fputc('x', pFile); >+ >+ /* unlock the pool for other process */ >+ rewind(pFile); >+ fputc('f', pFile); >+ >+ fclose(pFile); >+ pFile = NULL; >+ >+ return 0; >+ } >+ >+ fgets(line,256,pFile); >+ } >+ >+ /* if this code is reached something went wrong */ >+ error("Could not release IP address in IP pool"); >+ >+ if(pFile != NULL) >+ { >+ fclose(pFile); >+ } >+ >+ return -1; >+} >+ >+/* Checks if a stale process blocks the ippool >+ and unbliocks the ippool if blocked by a pid of a stale process */ >+static int check_stale_pool_blocking() >+{ >+ /* open the ippool file */ >+ FILE *pFile; >+ >+ char line[256]; >+ char indicator; >+ short counter = 0; >+ int position = 0; >+ char pidBuffer[10]; >+ FILE *pProcessFile; >+ char processFilePath[30]; >+ >+ pFile = fopen(usergroup,"r+"); >+ >+ if(pFile == NULL) >+ { >+ error("The IP pool file could not be found!"); >+ return -1; >+ }else{ >+ fgets(line,256,pFile); >+ indicator = line[0]; >+ } >+ >+ switch(indicator) >+ { >+ case 'f': >+ return 0; >+ >+ case 'b': >+ /* extract the process id */ >+ while(line[position+1] != 'f') >+ { >+ pidBuffer[position] = line[position+1]; >+ position++; >+ } >+ pidBuffer[position] = 0; >+ >+ /* check if the process is really alive */ >+ sprintf(processFilePath, "%s%s%s", "/proc/", pidBuffer, "/status"); >+ dbglog("Checking if process exists: %s", processFilePath); >+ >+ pProcessFile = fopen(processFilePath, "r+"); >+ if(pProcessFile == NULL){ >+ dbglog("Detected stale process id in IP pool --> Unblocking pool!"); >+ rewind(pFile); >+ for(counter = 0; counter < 10; counter++) >+ { >+ fputc('f', pFile); >+ } >+ dbglog("Unblocked pool from stale pid: %s", pidBuffer); >+ }else{ >+ fclose(pProcessFile); >+ } >+ } >+ fclose(pFile); >+ >+ return 0; >+} >+ >+/********************************************************************** >+* %FUNCTION: log_addr_user >+* writes a file with the name of the ip address given to the client >+* into a file under /var/run/ccert. >+* The file contains the user name >+* returns 0 if the file could be written >+* returns -1 if the could NOT be written >+***********************************************************************/ >+int log_addr_user(char* ipAddress, char* userName) >+{ >+ >+ char userGroupFolder[128]; >+ char filePathName[128]; >+ char fileOutBuffer[128]; >+ char *position; >+ FILE* pFile; >+ int pid; >+ >+ dbglog("==================== LOG ADDRESS AND USER =========================="); >+ /* remove the path from the usergroup */ >+ strcpy(userGroupFolder, usergroup); >+ position = strchr(userGroupFolder, '/'); >+ while(position != NULL){ >+ strcpy(userGroupFolder, position+1); >+ position = strchr(userGroupFolder, '/'); >+ if(position == NULL){ >+ break; >+ } >+ if(strlen(position) < 1){ >+ break; >+ } >+ } >+ >+ /* remove the file ending from the usergroup */ >+ position = strchr(userGroupFolder, '.'); >+ memset(position, 0, 1); >+ >+ sprintf(usergroup_dir, "%s%s%s", "/var/run/ccert/", userGroupFolder, "/"); >+ dbglog("Folder for this user group is: '%s'", usergroup_dir); >+ >+ /* build the filename */ >+ sprintf(filePathName, "%s%s", usergroup_dir, ipAddress); >+ dbglog("FILE: '%s': ", filePathName); >+ dbglog("IP: '%s' ----> user: '%s'", ipAddress, userName); >+ >+ pFile = fopen(filePathName, "w+"); >+ >+ /* directory does not exist? */ >+ if(pFile == NULL){ >+ dbglog("Creating path: '%s'", usergroup_dir); >+ mkdir(usergroup_dir, 0755); >+ } >+ >+ /* try again */ >+ pFile = fopen(filePathName, "w+"); >+ >+ /* still not there....we can not help you any more */ >+ if(pFile == NULL){ >+ error("Could not write var/run/ccert log entry!"); >+ return -1; >+ } >+ >+ /* write user name to file */ >+ sprintf(fileOutBuffer,"%s%s",userName,"\n"); >+ fputs(fileOutBuffer, pFile); >+ >+ /* write pid of this pppd process to file */ >+ pid = getpid(); >+ sprintf(fileOutBuffer,"%d%s",pid,"\n"); >+ fputs(fileOutBuffer, pFile); >+ >+ fclose(pFile); >+ >+ return 0; >+} >+ >+/********************************************************************** >+* %FUNCTION: clear_log_byaddr >+* erases the log file for an ip address >+* in folder /var/run/ccert. >+* returns 0 if the file could be written >+* returns -1 if the could NOT be written >+***********************************************************************/ >+int clear_log_byaddr(char* ipAddress) >+{ >+ int result = -1; >+ char filePathName[128]; >+ >+ dbglog("================= ERASE IPADDRESS LOG FILE ======================="); >+ >+ sprintf(filePathName,"%s%s", usergroup_dir, ipAddress); >+ dbglog("Trying to eraselog file for IP: %s FILE: '%s'", ipAddress, filePathName); >+ >+ /* remove the file */ >+ result = remove(filePathName); >+ >+ if(result != 0){ >+ error("Could NOT erase the log file: '%s'", filePathName); >+ return -1; >+ } >+ >+ return 0; >+} >+ >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/radiusclient.h ppp-wegener-despace-stripnum/pppd/plugins/radius/radiusclient.h >--- ppp-2.4.5-orig/pppd/plugins/radius/radiusclient.h 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/radiusclient.h 2013-01-14 18:00:56.984410508 +0100 >@@ -171,6 +171,12 @@ > /* From RFC 2869 */ > #define PW_ACCT_INTERIM_INTERVAL 85 /* integer */ > >+/* for eap tls */ >+ >+#define PW_EAP_MESSAGE 79 >+#define EAP_TLS_MAX_STRING_LEN 253 >+#define EAP_TLS_MAX_BUFFER_LEN 2048 >+ > /* Merit Experimental Extensions */ > > #define PW_USER_ID 222 /* string */ >@@ -181,6 +187,37 @@ > #define PW_SESSION_OCTETS_LIMIT 227 /* integer */ > #define PW_OCTETS_DIRECTION 228 /* integer */ > >+/* vendor specific attributes for cisco */ >+ >+#define PW_CISCO_AVPAIR 1 >+ >+/* vendor specific attributes for MS */ >+#define PW_MS_PRIMARY_DNS_SERVER 28 >+#define PW_MS_SECONDARY_DNS_SERVER 29 >+#define PW_MS_PRIMARY_NBNS_SERVER 30 >+#define PW_MS_SECONDARY_NBNS_SERVER 31 >+ >+/* vendor specific attributes for Siemens */ >+ >+#define PW_USERCERT_CN 221 >+#define PW_USERCERT_SN 222 >+#define PW_USERCERT_GN 223 >+#define PW_USERCERT_O 224 >+#define PW_USERCERT_OU 225 >+#define PW_USERCERT_ST 226 >+#define PW_USERCERT_L 227 >+#define PW_USERCERT_TITLE 228 >+#define PW_USERCERT_DESC 229 >+#define PW_USERCERT_NAME 230 >+#define PW_USERCERT_INITIALS 231 >+#define PW_USERCERT_PSEUDON 232 >+#define PW_USERCERT_ROLE 233 >+#define PW_USERCERT_UPN 240 >+#define PW_USERCERT_URI 241 >+#define PW_USERCERT_DNS 242 >+#define PW_USERCERT_EMAIL 243 >+#define PW_USERCERT_TCGID 244 >+ > /* Integer Translations */ > > /* SERVICE TYPES */ >@@ -290,8 +327,11 @@ > > > /* Vendor codes */ >+ > #define VENDOR_NONE (-1) >+#define VENDOR_CISCO 9 > #define VENDOR_MICROSOFT 311 >+#define VENDOR_SIEMENS 4329 > > /* Server data structures */ > >@@ -452,4 +492,12 @@ > > void rc_md5_calc __P((unsigned char *, unsigned char *, unsigned int)); > >+/* sendserver.c */ >+ >+/* 0 = NO EAP-Message-Authenticator needed. 1 = Needed */ >+extern int eap_tls_flag; >+ >+/* 0= do not use the ip pool, 1 = set peers IP by Framed-IP-Address attribute */ >+extern int ip_pool_flag; >+ > #endif /* RADIUSCLIENT_H */ >diff -rNu ppp-2.4.5-orig/pppd/plugins/radius/sendserver.c ppp-wegener-despace-stripnum/pppd/plugins/radius/sendserver.c >--- ppp-2.4.5-orig/pppd/plugins/radius/sendserver.c 2009-11-16 23:26:07.000000000 +0100 >+++ ppp-wegener-despace-stripnum/pppd/plugins/radius/sendserver.c 2005-04-13 20:28:48.000000000 +0200 >@@ -12,15 +12,95 @@ > * If the file is missing contact me at lf@elemental.net > * and I'll send you a copy. > * >+ * EAP TLS support by: >+ * michael.heiart@freenet.de >+ * > */ > > #include <includes.h> > #include <radiusclient.h> > #include <pathnames.h> > >+#define MD5_HASH_SIZE 16 >+#define PW_EAP_MESSAGE 79 >+#define PW_MESSAGE_AUTHENTICATOR 80 >+ > static void rc_random_vector (unsigned char *); > static int rc_check_reply (AUTH_HDR *, int, char *, unsigned char *, unsigned char); > >+static void hmac_md5(unsigned char *text, /* pointer to data stream */ >+ int text_len, /* length of data stream */ >+ unsigned char *key, /* pointer to authentication key */ >+ int key_len, /* length of authentication key */ >+ u_char *digest); /* write result here */ >+ >+/* hmac_hash for EAP Message -Authenticator */ >+void MD5Init (); >+void MD5Update (); >+void MD5Final (); >+ >+/* forward declaration */ >+static void Transform (); >+ >+/* Data structure for MD5 (Message-Digest) computation */ >+typedef struct { >+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ >+ UINT4 buf[4]; /* scratch buffer */ >+ unsigned char in[64]; /* input buffer */ >+ unsigned char digest[16]; /* actual digest after MD5Final call */ >+} MD5_CTX; >+ >+static unsigned char PADDING[64] = { >+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, >+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 >+}; >+ >+/* F, G, H and I are basic MD5 functions */ >+#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) >+#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) >+#define H(x, y, z) ((x) ^ (y) ^ (z)) >+#define I(x, y, z) ((y) ^ ((x) | (~z))) >+ >+/* ROTATE_LEFT rotates x left n bits */ >+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) >+ >+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ >+/* Rotation is separate from addition to prevent recomputation */ >+#define FF(a, b, c, d, x, s, ac) \ >+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ >+ (a) = ROTATE_LEFT ((a), (s)); \ >+ (a) += (b); \ >+ } >+#define GG(a, b, c, d, x, s, ac) \ >+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ >+ (a) = ROTATE_LEFT ((a), (s)); \ >+ (a) += (b); \ >+ } >+#define HH(a, b, c, d, x, s, ac) \ >+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ >+ (a) = ROTATE_LEFT ((a), (s)); \ >+ (a) += (b); \ >+ } >+#define II(a, b, c, d, x, s, ac) \ >+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ >+ (a) = ROTATE_LEFT ((a), (s)); \ >+ (a) += (b); \ >+ } >+ >+#ifdef __STDC__ >+#define UL(x) x##U >+#else >+#define UL(x) x >+#endif >+ >+ >+ > /* > * Function: rc_pack_list > * >@@ -291,6 +371,70 @@ > sin->sin_addr.s_addr = htonl (auth_ipaddr); > sin->sin_port = htons ((unsigned short) data->svc_port); > >+ /* Build the hashMD5Input for an Message-Authenticator */ >+ if(eap_tls_flag == 1 && data->code != PW_ACCOUNTING_REQUEST) >+ { >+ /* Set Code and Id */ >+ unsigned char hashInput[2048]; >+ unsigned char *pHashInput = hashInput; >+ int inputSize = 0; >+ /* Length of the hole RADIUS packet for md5 hash */ >+ unsigned short slen = 0; >+ unsigned char hmac_md5hash[16]; >+ >+ >+ hashInput[0]=data->code; >+ hashInput[1]=data->seq_nbr; >+ inputSize = 2; >+ >+ /* The length of the data from auth->data /which are attributes) >+ + 18 Bytes for the Message Authenticator */ >+ slen = htons ((unsigned short) total_length + 18); >+ memcpy(pHashInput+inputSize,&slen,2); >+ inputSize += 2; >+ >+ /* The RADIUS authenticator !!THIS IS NOT THE MESSAGE AUTHENTICATOR!! */ >+ memcpy(pHashInput+inputSize,auth->vector,AUTH_VECTOR_LEN); >+ inputSize += AUTH_VECTOR_LEN; >+ >+ /* The Attributes WITHOUT the Message Authenticator */ >+ memcpy(pHashInput+inputSize,auth->data,total_length); >+ >+ /* total_length includes header and RADIUS authenticator */ >+ /* what we add are only the attributes. Therefore -20 */ >+ inputSize += total_length - 20; >+ >+ /* The Message Authenticator */ >+ >+ /* Set Attribuet Type Message Authenticator */ >+ hashInput[inputSize] = 80; >+ inputSize++; >+ >+ /* Set length */ >+ hashInput[inputSize] = 18; >+ inputSize++; >+ >+ /* Set the 16 bytes of the value to zero */ >+ /* do not make pHashInput higher because real hmac-MD5 hash will be copied here */ >+ memset(pHashInput+inputSize,0,16); >+ inputSize += 16; >+ >+ secretlen = strlen (secret); >+ hmac_md5((unsigned char*)pHashInput, inputSize,(unsigned char*)secret, secretlen, hmac_md5hash); >+ >+ /* the actual RADIUS PACKET needs the new length. >+ Packet will be 18 Bytes larger because of Message Authenticator */ >+ total_length += 18; >+ auth->length = htons ((unsigned short) total_length); >+ >+ /* copy the hmac_md5hash in the hashInput */ >+ memcpy(pHashInput+inputSize-16,hmac_md5hash,16); >+ >+ /* now the the hashInput from position 20 to end contains what data should be */ >+ memcpy(auth->data, pHashInput+20, total_length-20); >+ >+ } /* end if Message Authenticator */ >+ > for (;;) > { > sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0, >@@ -370,13 +514,16 @@ > > if ((recv_auth->code == PW_ACCESS_ACCEPT) || > (recv_auth->code == PW_PASSWORD_ACK) || >- (recv_auth->code == PW_ACCOUNTING_RESPONSE)) >+ (recv_auth->code == PW_ACCOUNTING_RESPONSE)|| >+ (recv_auth->code == PW_ACCESS_CHALLENGE)||/* EAP TLS: RADIUS SERVER will send Challenge */ >+ (recv_auth->code ==PW_ACCESS_REJECT)) > { > result = OK_RC; > } > else > { > result = BADRESP_RC; >+ dbglog("rc_send_server thinks that this code is bad!!!"); > } > > return (result); >@@ -467,6 +614,12 @@ > return (BADRESP_RC); > } > >+ /* make sure that ACCESS_REJECT is flagged as BADRESP */ >+ if(auth->code == PW_ACCESS_REJECT){ >+ dbglog("rc_check_reply: received ACCESS REJECT"); >+ return (BADRESP_RC); >+ } >+ > return (OK_RC); > > } >@@ -518,3 +671,289 @@ > > return; > } >+ >+ >+/* The routine MD5Init initializes the message-digest context >+ mdContext. All fields are set to zero. >+ */ >+void MD5Init (mdContext) >+MD5_CTX *mdContext; >+{ >+ mdContext->i[0] = mdContext->i[1] = (UINT4)0; >+ >+ /* Load magic initialization constants. >+ */ >+ mdContext->buf[0] = (UINT4)0x67452301; >+ mdContext->buf[1] = (UINT4)0xefcdab89; >+ mdContext->buf[2] = (UINT4)0x98badcfe; >+ mdContext->buf[3] = (UINT4)0x10325476; >+} >+ >+/* The routine MD5Update updates the message-digest context to >+ account for the presence of each of the characters inBuf[0..inLen-1] >+ in the message whose digest is being computed. >+ */ >+void MD5Update (mdContext, inBuf, inLen) >+MD5_CTX *mdContext; >+unsigned char *inBuf; >+unsigned int inLen; >+{ >+ UINT4 in[16]; >+ int mdi; >+ unsigned int i, ii; >+ >+ /* compute number of bytes mod 64 */ >+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); >+ >+ /* update number of bits */ >+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) >+ mdContext->i[1]++; >+ mdContext->i[0] += ((UINT4)inLen << 3); >+ mdContext->i[1] += ((UINT4)inLen >> 29); >+ >+ while (inLen--) { >+ /* add new character to buffer, increment mdi */ >+ mdContext->in[mdi++] = *inBuf++; >+ >+ /* transform if necessary */ >+ if (mdi == 0x40) { >+ for (i = 0, ii = 0; i < 16; i++, ii += 4) >+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | >+ (((UINT4)mdContext->in[ii+2]) << 16) | >+ (((UINT4)mdContext->in[ii+1]) << 8) | >+ ((UINT4)mdContext->in[ii]); >+ Transform (mdContext->buf, in); >+ mdi = 0; >+ } >+ } >+} >+ >+/* The routine MD5Final terminates the message-digest computation and >+ ends with the desired message digest in mdContext->digest[0...15]. >+ */ >+void MD5Final (hash, mdContext) >+unsigned char hash[]; >+MD5_CTX *mdContext; >+{ >+ UINT4 in[16]; >+ int mdi; >+ unsigned int i, ii; >+ unsigned int padLen; >+ >+ /* save number of bits */ >+ in[14] = mdContext->i[0]; >+ in[15] = mdContext->i[1]; >+ >+ /* compute number of bytes mod 64 */ >+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F); >+ >+ /* pad out to 56 mod 64 */ >+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); >+ MD5Update (mdContext, PADDING, padLen); >+ >+ /* append length in bits and transform */ >+ for (i = 0, ii = 0; i < 14; i++, ii += 4) >+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | >+ (((UINT4)mdContext->in[ii+2]) << 16) | >+ (((UINT4)mdContext->in[ii+1]) << 8) | >+ ((UINT4)mdContext->in[ii]); >+ Transform (mdContext->buf, in); >+ >+ /* store buffer in digest */ >+ for (i = 0, ii = 0; i < 4; i++, ii += 4) { >+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); >+ mdContext->digest[ii+1] = >+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); >+ mdContext->digest[ii+2] = >+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); >+ mdContext->digest[ii+3] = >+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); >+ } >+ memcpy(hash, mdContext->digest, 16); >+} >+ >+/* Basic MD5 step. Transforms buf based on in. >+ */ >+static void Transform (buf, in) >+UINT4 *buf; >+UINT4 *in; >+{ >+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; >+ >+ /* Round 1 */ >+#define S11 7 >+#define S12 12 >+#define S13 17 >+#define S14 22 >+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ >+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ >+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ >+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ >+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ >+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ >+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ >+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ >+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ >+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ >+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ >+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ >+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ >+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ >+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ >+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ >+ >+ /* Round 2 */ >+#define S21 5 >+#define S22 9 >+#define S23 14 >+#define S24 20 >+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ >+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ >+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ >+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ >+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ >+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ >+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ >+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ >+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ >+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ >+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ >+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ >+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ >+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ >+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ >+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ >+ >+ /* Round 3 */ >+#define S31 4 >+#define S32 11 >+#define S33 16 >+#define S34 23 >+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ >+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ >+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ >+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ >+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ >+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ >+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ >+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ >+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ >+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ >+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ >+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ >+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ >+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ >+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ >+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ >+ >+ /* Round 4 */ >+#define S41 6 >+#define S42 10 >+#define S43 15 >+#define S44 21 >+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ >+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ >+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ >+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ >+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ >+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ >+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ >+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ >+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ >+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ >+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ >+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ >+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ >+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ >+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ >+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ >+ >+ buf[0] += a; >+ buf[1] += b; >+ buf[2] += c; >+ buf[3] += d; >+} >+ >+/* >+** Function: hmac_md5 >+*/ >+ >+static void >+hmac_md5(text, text_len, key, key_len, digest) >+unsigned char* text; /* pointer to data stream */ >+int text_len; /* length of data stream */ >+unsigned char* key; /* pointer to authentication key */ >+int key_len; /* length of authentication key */ >+u_char* digest; /* caller digest to be filled in */ >+ >+{ >+ MD5_CTX context; >+ unsigned char k_ipad[65]; /* inner padding - >+ * key XORd with ipad >+ */ >+ unsigned char k_opad[65]; /* outer padding - >+ * key XORd with opad >+ */ >+ unsigned char tk[16]; >+ int i; >+ /* if key is longer than 64 bytes reset it to key=MD5(key) */ >+ if (key_len > 64) { >+ >+ MD5_CTX tctx; >+ >+ MD5Init(&tctx); >+ MD5Update(&tctx, key, key_len); >+ MD5Final(tk, &tctx); >+ >+ key = tk; >+ key_len = 16; >+ } >+ >+ /* >+ * the HMAC_MD5 transform looks like: >+ * >+ * MD5(K XOR opad, MD5(K XOR ipad, text)) >+ * >+ * where K is an n byte key >+ * ipad is the byte 0x36 repeated 64 times >+ >+ * opad is the byte 0x5c repeated 64 times >+ * and text is the data being protected >+ */ >+ >+ /* start out by storing key in pads */ >+ bzero( k_ipad, sizeof k_ipad); >+ bzero( k_opad, sizeof k_opad); >+ bcopy( key, k_ipad, key_len); >+ bcopy( key, k_opad, key_len); >+ >+ /* XOR key with ipad and opad values */ >+ for (i=0; i<64; i++) { >+ k_ipad[i] ^= 0x36; >+ k_opad[i] ^= 0x5c; >+ } >+ >+ /* >+ * perform inner MD5 >+ */ >+ MD5Init(&context); /* init context for 1st >+ * pass */ >+ >+ MD5Update(&context, k_ipad, 64); /* start with inner pad */ >+ >+ MD5Update(&context, text, text_len); /* then text of datagram */ >+ >+ MD5Final(digest, &context); /* finish up 1st pass */ >+ >+ /* >+ * perform outer MD5 >+ */ >+ MD5Init(&context); /* init context for 2nd >+ * pass */ >+ >+ MD5Update(&context, k_opad, 64); /* start with outer pad */ >+ >+ MD5Update(&context, digest, 16); /* then results of 1st >+ * hash */ >+ MD5Final(digest, &context); /* finish up 2nd pass */ >+} >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 648217
:
678423
|
678433
|
678842
|
679094
|
718350