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 678842 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 v0.2
ppp-2.4.5-radius-eaptls-v0.2.patch (text/plain), 44.27 KB, created by
Michal Bruncko
on 2013-01-15 15:25:34 UTC
(
hide
)
Description:
RADIUS EAP-TLS/EAP-TTLS Patch v0.2
Filename:
MIME Type:
Creator:
Michal Bruncko
Created:
2013-01-15 15:25:34 UTC
Size:
44.27 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, >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-15 15:23:28.741407706 +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,13 @@ > 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 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 +144,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 +166,13 @@ > > char pppd_version[] = VERSION; > >+/* 0 = NO EAP-Message-Authenticator needed. 1 = Needed */ >+int eap_tls_flag = 0; >+ >+/* extracted data from RADIUS user certificate attributes >+ * (requires FreeRadius patch) >+ */ >+ > /********************************************************************** > * %FUNCTION: plugin_init > * %ARGUMENTS: >@@ -154,6 +191,15 @@ > 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 +213,14 @@ > > add_options(Options); > >+ eap_tls_flag = 0; >+ >+ rstate.radius_cert_UPN[0]='\0'; >+ rstate.radius_cert_CN[0]='\0'; >+ rstate.radius_cert_TCGID[0]='\0'; >+ >+ rstate.state_attr_len = 0; >+ > info("RADIUS plugin initialized."); > } > >@@ -242,6 +296,7 @@ > radius_pap_auth(char *user, > char *passwd, > char **msgp, >+ > struct wordlist **paddrs, > struct wordlist **popts) > { >@@ -309,7 +364,13 @@ > rc_avpair_free(received); > rc_avpair_free(send); > >- return (result == OK_RC) ? 1 : 0; >+ if(result == OK_RC){ >+ >+ 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 */ >+ } > } > > /********************************************************************** >@@ -487,6 +548,7 @@ > > rc_avpair_free(received); > rc_avpair_free (send); >+ > return (result == OK_RC); > } > >@@ -543,6 +605,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 +622,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 */ >@@ -706,11 +706,68 @@ > 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; >+ } >+ } >+ } >+ } /*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 +811,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 */ > } >@@ -1029,7 +1177,7 @@ > case EXIT_CONNECT_TIME: > av_type = PW_ACCT_SESSION_TIMEOUT; > break; >- >+ > #ifdef MAXOCTETS > case EXIT_TRAFFIC_LIMIT: > av_type = PW_NAS_REQUEST; >@@ -1304,3 +1452,223 @@ > { > 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); >+ >+ 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; >+ >+} >+ >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-15 15:25:15.280413341 +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,9 @@ > > 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; >+ > #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