Using a struct to represent an on-the-wire format is basically
broken, since the compiler can add padding between members or
assume alignment for the struct. Instead we just use arrays
of unsigned char and define offsets in the arrays for the various
fields.
-#define RCSID "$Id: chap_ms.c,v 1.33 2004/11/12 09:57:43 paulus Exp $"
+#define RCSID "$Id: chap_ms.c,v 1.34 2004/11/15 22:13:26 paulus Exp $"
static void NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE]));
static void ChallengeResponse __P((u_char *, u_char *, u_char[24]));
static void ChapMS_NT __P((u_char *, char *, int, u_char[24]));
static void NTPasswordHash __P((char *, int, u_char[MD4_SIGNATURE_SIZE]));
static void ChallengeResponse __P((u_char *, u_char *, u_char[24]));
static void ChapMS_NT __P((u_char *, char *, int, u_char[24]));
-static void ChapMS2_NT __P((char *, u_char[16], char *, char *, int,
+static void ChapMS2_NT __P((u_char *, u_char[16], char *, char *, int,
u_char[24]));
static void GenerateAuthenticatorResponsePlain
__P((char*, int, u_char[24], u_char[16], u_char *,
char *, u_char[41]));
#ifdef MSLANMAN
u_char[24]));
static void GenerateAuthenticatorResponsePlain
__P((char*, int, u_char[24], u_char[16], u_char *,
char *, u_char[41]));
#ifdef MSLANMAN
-static void ChapMS_LANMan __P((u_char *, char *, int, MS_ChapResponse *));
+static void ChapMS_LANMan __P((u_char *, char *, int, u_char *));
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
- MS_ChapResponse *rmd;
- MS_ChapResponse md;
+ unsigned char md[MS_CHAP_RESPONSE_LEN];
int diff;
int challenge_len, response_len;
int diff;
int challenge_len, response_len;
if (response_len != MS_CHAP_RESPONSE_LEN)
goto bad;
if (response_len != MS_CHAP_RESPONSE_LEN)
goto bad;
- rmd = (MS_ChapResponse *) response;
-
+ if (!response[MS_CHAP_USENT]) {
/* Should really propagate this into the error packet. */
notice("Peer request for LANMAN auth not supported");
goto bad;
/* Should really propagate this into the error packet. */
notice("Peer request for LANMAN auth not supported");
goto bad;
#endif
/* Generate the expected response. */
#endif
/* Generate the expected response. */
- ChapMS(challenge, (char *)secret, secret_len, &md);
+ ChapMS(challenge, (char *)secret, secret_len, md);
#ifdef MSLANMAN
/* Determine which part of response to verify against */
#ifdef MSLANMAN
/* Determine which part of response to verify against */
- if (!rmd->UseNT[0])
- diff = memcmp(&rmd->LANManResp, &md.LANManResp,
- sizeof(md.LANManResp));
+ if (!response[MS_CHAP_USENT])
+ diff = memcmp(&response[MS_CHAP_LANMANRESP],
+ &md[MS_CHAP_LANMANRESP], MS_CHAP_LANMANRESP_LEN);
- diff = memcmp(&rmd->NTResp, &md.NTResp, sizeof(md.NTResp));
+ diff = memcmp(&response[MS_CHAP_NTRESP], &md[MS_CHAP_NTRESP],
+ MS_CHAP_NTRESP_LEN);
if (diff == 0) {
slprintf(message, message_space, "Access granted");
if (diff == 0) {
slprintf(message, message_space, "Access granted");
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
unsigned char *challenge, unsigned char *response,
char *message, int message_space)
{
- MS_Chap2Response *rmd;
- MS_Chap2Response md;
+ unsigned char md[MS_CHAP2_RESPONSE_LEN];
char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
int challenge_len, response_len;
char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
int challenge_len, response_len;
if (response_len != MS_CHAP2_RESPONSE_LEN)
goto bad; /* not even the right length */
if (response_len != MS_CHAP2_RESPONSE_LEN)
goto bad; /* not even the right length */
- rmd = (MS_Chap2Response *) response;
-
/* Generate the expected response and our mutual auth. */
/* Generate the expected response and our mutual auth. */
- ChapMS2(challenge, rmd->PeerChallenge, name,
- (char *)secret, secret_len, &md,
+ ChapMS2(challenge, &response[MS_CHAP2_PEER_CHALLENGE], name,
+ (char *)secret, secret_len, md,
(unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
/* compare MDs and send the appropriate status */
(unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
/* compare MDs and send the appropriate status */
* Special thanks to Alex Swiridov <say@real.kharkov.ua> for
* help debugging this.
*/
* Special thanks to Alex Swiridov <say@real.kharkov.ua> for
* help debugging this.
*/
- if (memcmp(md.NTResp, rmd->NTResp, sizeof(md.NTResp)) == 0) {
- if (rmd->Flags[0])
+ if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_NTRESP_LEN) == 0) {
+ if (response[MS_CHAP2_FLAGS])
slprintf(message, message_space, "S=%s", saresponse);
else
slprintf(message, message_space, "S=%s M=%s",
slprintf(message, message_space, "S=%s", saresponse);
else
slprintf(message, message_space, "S=%s M=%s",
{
challenge++; /* skip length, should be 8 */
*response++ = MS_CHAP_RESPONSE_LEN;
{
challenge++; /* skip length, should be 8 */
*response++ = MS_CHAP_RESPONSE_LEN;
- ChapMS(challenge, secret, secret_len, (MS_ChapResponse *) response);
+ ChapMS(challenge, secret, secret_len, response);
- our_name, secret, secret_len,
- (MS_Chap2Response *) response, private,
+ our_name, secret, secret_len, response, private,
MS_CHAP2_AUTHENTICATEE);
}
MS_CHAP2_AUTHENTICATEE);
}
-ChapMS2_NT(char *rchallenge, u_char PeerChallenge[16], char *username,
+ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username,
char *secret, int secret_len, u_char NTResponse[24])
{
u_char unicodePassword[MAX_NT_PASSWORD * 2];
u_char PasswordHash[MD4_SIGNATURE_SIZE];
u_char Challenge[8];
char *secret, int secret_len, u_char NTResponse[24])
{
u_char unicodePassword[MAX_NT_PASSWORD * 2];
u_char PasswordHash[MD4_SIGNATURE_SIZE];
u_char Challenge[8];
- ChallengeHash(PeerChallenge, (unsigned char *)rchallenge, username,
- Challenge);
+ ChallengeHash(PeerChallenge, rchallenge, username, Challenge);
/* Hash the Unicode version of the secret (== password). */
ascii2unicode(secret, secret_len, unicodePassword);
/* Hash the Unicode version of the secret (== password). */
ascii2unicode(secret, secret_len, unicodePassword);
static void
ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
static void
ChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,
- MS_ChapResponse *response)
+ unsigned char *response)
{
int i;
u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
{
int i;
u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
DesEncrypt( StdText, PasswordHash + 0 );
(void) DesSetkey(UcasePassword + 7);
DesEncrypt( StdText, PasswordHash + 8 );
DesEncrypt( StdText, PasswordHash + 0 );
(void) DesSetkey(UcasePassword + 7);
DesEncrypt( StdText, PasswordHash + 8 );
- ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
+ ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]);
void
ChapMS(u_char *rchallenge, char *secret, int secret_len,
void
ChapMS(u_char *rchallenge, char *secret, int secret_len,
- MS_ChapResponse *response)
+ unsigned char *response)
- BZERO(response, sizeof(*response));
+ BZERO(response, MS_CHAP_RESPONSE_LEN);
- ChapMS_NT(rchallenge, secret, secret_len, response->NTResp);
+ ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);
- ChapMS_LANMan(rchallenge, secret, secret_len, response);
+ ChapMS_LANMan(rchallenge, secret, secret_len, &response);
/* preferred method is set by option */
/* preferred method is set by option */
- response->UseNT[0] = !ms_lanman;
+ response[MS_CHAP_USENT] = !ms_lanman;
- response->UseNT[0] = 1;
+ response[MS_CHAP_USENT] = 1;
- * If PeerChallenge is NULL, one is generated and response->PeerChallenge
- * is filled in. Call this way when generating a response.
- * If PeerChallenge is supplied, it is copied into response->PeerChallenge.
+ * If PeerChallenge is NULL, one is generated and the PeerChallenge
+ * field of response is filled in. Call this way when generating a response.
+ * If PeerChallenge is supplied, it is copied into the PeerChallenge field.
* Call this way when verifying a response (or debugging).
* Call this way when verifying a response (or debugging).
- * Do not call with PeerChallenge = response->PeerChallenge.
+ * Do not call with PeerChallenge = response.
- * response->PeerChallenge is then used for calculation of the
+ * The PeerChallenge field of response is then used for calculation of the
* Authenticator Response.
*/
void
ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
* Authenticator Response.
*/
void
ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
- char *user, char *secret, int secret_len, MS_Chap2Response *response,
+ char *user, char *secret, int secret_len, unsigned char *response,
u_char authResponse[], int authenticator)
{
/* ARGSUSED */
u_char authResponse[], int authenticator)
{
/* ARGSUSED */
- u_char *p = response->PeerChallenge;
+ u_char *p = &response[MS_CHAP2_PEER_CHALLENGE];
int i;
BZERO(response, sizeof(*response));
/* Generate the Peer-Challenge if requested, or copy it if supplied. */
if (!PeerChallenge)
int i;
BZERO(response, sizeof(*response));
/* Generate the Peer-Challenge if requested, or copy it if supplied. */
if (!PeerChallenge)
- for (i = 0; i < sizeof(response->PeerChallenge); i++)
+ for (i = 0; i < MS_CHAP2_PEER_CHAL_LEN; i++)
*p++ = (u_char) (drand48() * 0xff);
else
*p++ = (u_char) (drand48() * 0xff);
else
- BCOPY(PeerChallenge, response->PeerChallenge,
- sizeof(response->PeerChallenge));
+ BCOPY(PeerChallenge, &response[MS_CHAP2_PEER_CHALLENGE],
+ MS_CHAP2_PEER_CHAL_LEN);
/* Generate the NT-Response */
/* Generate the NT-Response */
- ChapMS2_NT((char *)rchallenge, response->PeerChallenge, user,
- secret, secret_len, response->NTResp);
+ ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user,
+ secret, secret_len, &response[MS_CHAP2_NTRESP]);
/* Generate the Authenticator Response. */
/* Generate the Authenticator Response. */
- GenerateAuthenticatorResponsePlain(secret, secret_len, response->NTResp,
- response->PeerChallenge, rchallenge,
- user, authResponse);
+ GenerateAuthenticatorResponsePlain(secret, secret_len,
+ &response[MS_CHAP2_NTRESP],
+ &response[MS_CHAP2_PEER_CHALLENGE],
+ rchallenge, user, authResponse);
- SetMasterKeys(secret, secret_len, response->NTResp, authenticator);
+ SetMasterKeys(secret, secret_len,
+ &response[MS_CHAP2_NTRESP], authenticator);
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: chap_ms.h,v 1.12 2004/11/09 22:49:05 paulus Exp $
+ * $Id: chap_ms.h,v 1.13 2004/11/15 22:13:26 paulus Exp $
*/
#ifndef __CHAPMS_INCLUDE__
*/
#ifndef __CHAPMS_INCLUDE__
#define MS_CHAP_ERROR_CHANGING_PASSWORD 709
/*
#define MS_CHAP_ERROR_CHANGING_PASSWORD 709
/*
- * Apparently gcc on ARM gives all structures 4-byte alignment
- * by default. This tells gcc that these structures may be
- * unaligned and may not have extra padding inside them.
+ * Offsets within the response field for MS-CHAP
-#ifdef __GNUC__
-#define PACKED __attribute__((__packed__))
-#else
-#define PACKED
-#endif
-
-/*
- * Use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
- * in case this struct gets padded.
- */
-typedef struct {
- u_char LANManResp[24];
- u_char NTResp[24];
- u_char UseNT[1]; /* If 1, ignore the LANMan response field */
-} MS_ChapResponse PACKED;
+#define MS_CHAP_LANMANRESP 0
+#define MS_CHAP_LANMANRESP_LEN 24
+#define MS_CHAP_NTRESP 24
+#define MS_CHAP_NTRESP_LEN 24
+#define MS_CHAP_USENT 48
- * Use MS_CHAP2_RESPONSE_LEN, rather than sizeof(MS_Chap2Response),
- * in case this struct gets padded.
+ * Offsets within the response field for MS-CHAP2
-typedef struct {
- u_char PeerChallenge[16];
- u_char Reserved[8]; /* Must be zero */
- u_char NTResp[24];
- u_char Flags[1]; /* Must be zero */
-} MS_Chap2Response PACKED;
+#define MS_CHAP2_PEER_CHALLENGE 0
+#define MS_CHAP2_PEER_CHAL_LEN 16
+#define MS_CHAP2_RESERVED_LEN 8
+#define MS_CHAP2_NTRESP 24
+#define MS_CHAP2_NTRESP_LEN 24
+#define MS_CHAP2_FLAGS 48
#ifdef MPPE
#include <net/ppp-comp.h> /* MPPE_MAX_KEY_LEN */
#ifdef MPPE
#include <net/ppp-comp.h> /* MPPE_MAX_KEY_LEN */
#define MS_CHAP2_AUTHENTICATEE 0
#define MS_CHAP2_AUTHENTICATOR 1
#define MS_CHAP2_AUTHENTICATEE 0
#define MS_CHAP2_AUTHENTICATOR 1
-void ChapMS __P((u_char *, char *, int, MS_ChapResponse *));
+void ChapMS __P((u_char *, char *, int, u_char *));
void ChapMS2 __P((u_char *, u_char *, char *, char *, int,
void ChapMS2 __P((u_char *, u_char *, char *, char *, int,
- MS_Chap2Response *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int));
+ u_char *, u_char[MS_AUTH_RESPONSE_LENGTH+1], int));
#ifdef MPPE
void mppe_set_keys __P((u_char *, u_char[MD4_SIGNATURE_SIZE]));
void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
#ifdef MPPE
void mppe_set_keys __P((u_char *, u_char[MD4_SIGNATURE_SIZE]));
void mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
*
***********************************************************************/
static char const RCSID[] =
*
***********************************************************************/
static char const RCSID[] =
-"$Id: radius.c,v 1.28 2004/11/14 10:27:57 paulus Exp $";
+"$Id: radius.c,v 1.29 2004/11/15 22:13:26 paulus Exp $";
#include "pppd.h"
#include "chap-new.h"
#include "pppd.h"
#include "chap-new.h"
case CHAP_MICROSOFT:
{
/* MS-CHAP-Challenge and MS-CHAP-Response */
case CHAP_MICROSOFT:
{
/* MS-CHAP-Challenge and MS-CHAP-Response */
- MS_ChapResponse *rmd = (MS_ChapResponse *) response;
u_char *p = cpassword;
if (response_len != MS_CHAP_RESPONSE_LEN)
return 0;
*p++ = id;
/* The idiots use a different field order in RADIUS than PPP */
u_char *p = cpassword;
if (response_len != MS_CHAP_RESPONSE_LEN)
return 0;
*p++ = id;
/* The idiots use a different field order in RADIUS than PPP */
- memcpy(p, rmd->UseNT, sizeof(rmd->UseNT));
- p += sizeof(rmd->UseNT);
- memcpy(p, rmd->LANManResp, sizeof(rmd->LANManResp));
- p += sizeof(rmd->LANManResp);
- memcpy(p, rmd->NTResp, sizeof(rmd->NTResp));
+ *p++ = response[MS_CHAP_USENT];
+ memcpy(p, response, MS_CHAP_LANMANRESP_LEN + MS_CHAP_NTRESP_LEN);
rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
challenge, challenge_len, VENDOR_MICROSOFT);
rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
challenge, challenge_len, VENDOR_MICROSOFT);
case CHAP_MICROSOFT_V2:
{
/* MS-CHAP-Challenge and MS-CHAP2-Response */
case CHAP_MICROSOFT_V2:
{
/* MS-CHAP-Challenge and MS-CHAP2-Response */
- MS_Chap2Response *rmd = (MS_Chap2Response *) response;
u_char *p = cpassword;
if (response_len != MS_CHAP2_RESPONSE_LEN)
return 0;
*p++ = id;
/* The idiots use a different field order in RADIUS than PPP */
u_char *p = cpassword;
if (response_len != MS_CHAP2_RESPONSE_LEN)
return 0;
*p++ = id;
/* The idiots use a different field order in RADIUS than PPP */
- memcpy(p, rmd->Flags, sizeof(rmd->Flags));
- p += sizeof(rmd->Flags);
- memcpy(p, rmd->PeerChallenge, sizeof(rmd->PeerChallenge));
- p += sizeof(rmd->PeerChallenge);
- memcpy(p, rmd->Reserved, sizeof(rmd->Reserved));
- p += sizeof(rmd->Reserved);
- memcpy(p, rmd->NTResp, sizeof(rmd->NTResp));
+ *p++ = response[MS_CHAP2_FLAGS];
+ memcpy(p, response, (MS_CHAP2_PEER_CHAL_LEN + MS_CHAP2_RESERVED_LEN
+ + MS_CHAP2_NTRESP_LEN));
rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
challenge, challenge_len, VENDOR_MICROSOFT);
rc_avpair_add(&send, PW_MS_CHAP_CHALLENGE,
challenge, challenge_len, VENDOR_MICROSOFT);
u_char *lm_response = NULL;
int nt_response_size = 0;
int lm_response_size = 0;
u_char *lm_response = NULL;
int nt_response_size = 0;
int lm_response_size = 0;
- MS_ChapResponse *rmd = (MS_ChapResponse *) response;
u_char session_key[16];
if (response_len != MS_CHAP_RESPONSE_LEN)
break; /* not even the right length */
/* Determine which part of response to verify against */
u_char session_key[16];
if (response_len != MS_CHAP_RESPONSE_LEN)
break; /* not even the right length */
/* Determine which part of response to verify against */
- if (rmd->UseNT[0]) {
- nt_response = rmd->NTResp;
- nt_response_size = sizeof(rmd->NTResp);
+ if (response[MS_CHAP_USENT]) {
+ nt_response = &response[MS_CHAP_NTRESP];
+ nt_response_size = MS_CHAP_NTRESP_LEN;
- lm_response = rmd->LANManResp;
- lm_response_size = sizeof(rmd->LANManResp);
+ lm_response = &response[MS_CHAP_LANMANRESP];
+ lm_response_size = MS_CHAP_LANMANRESP_LEN;
#else
/* Should really propagate this into the error packet. */
notice("Peer request for LANMAN auth not supported");
#else
/* Should really propagate this into the error packet. */
notice("Peer request for LANMAN auth not supported");
- challenge,
- challenge_len,
- lm_response,
- lm_response ? lm_response_size: 0,
- nt_response,
- nt_response ? nt_response_size: 0,
+ challenge, challenge_len,
+ lm_response, lm_response_size,
+ nt_response, nt_response_size,
session_key,
&error_string) == AUTHENTICATED) {
mppe_set_keys(challenge, session_key);
session_key,
&error_string) == AUTHENTICATED) {
mppe_set_keys(challenge, session_key);
case CHAP_MICROSOFT_V2:
{
case CHAP_MICROSOFT_V2:
{
- MS_Chap2Response *rmd = (MS_Chap2Response *) response;
u_char Challenge[8];
u_char session_key[MD4_SIGNATURE_SIZE];
char *error_string = NULL;
u_char Challenge[8];
u_char session_key[MD4_SIGNATURE_SIZE];
char *error_string = NULL;
if (response_len != MS_CHAP2_RESPONSE_LEN)
break; /* not even the right length */
if (response_len != MS_CHAP2_RESPONSE_LEN)
break; /* not even the right length */
- ChallengeHash(rmd->PeerChallenge, challenge, user, Challenge);
+ ChallengeHash(&response[MS_CHAP2_PEER_CHALLENGE], challenge,
+ user, Challenge);
/* ship off to winbind, and check */
/* ship off to winbind, and check */
- Challenge,
- 8,
- NULL,
- 0,
- rmd->NTResp,
- sizeof(rmd->NTResp),
-
+ Challenge, 8,
+ NULL, 0,
+ &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_NTRESP_LEN,
session_key,
&error_string) == AUTHENTICATED) {
GenerateAuthenticatorResponse(session_key,
session_key,
&error_string) == AUTHENTICATED) {
GenerateAuthenticatorResponse(session_key,
- rmd->NTResp, rmd->PeerChallenge,
- challenge, user,
- saresponse);
- mppe_set_keys2(session_key, rmd->NTResp, MS_CHAP2_AUTHENTICATOR);
- if (rmd->Flags[0]) {
+ &response[MS_CHAP2_NTRESP],
+ &response[MS_CHAP2_PEER_CHALLENGE],
+ challenge, user, saresponse);
+ mppe_set_keys2(session_key, &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_AUTHENTICATOR);
+ if (response[MS_CHAP2_FLAGS]) {
slprintf(message, message_space, "S=%s", saresponse);
} else {
slprintf(message, message_space, "S=%s M=%s",
slprintf(message, message_space, "S=%s", saresponse);
} else {
slprintf(message, message_space, "S=%s M=%s",