chap_ms.c

来自「自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多」· C语言 代码 · 共 941 行 · 第 1/2 页

C
941
字号
{    SHA1_CTX	sha1Context;    u_char	sha1Hash[SHA1_SIGNATURE_SIZE];    char	*user;    /* remove domain from "domain\username" */    if ((user = strrchr(username, '\\')) != NULL)	++user;    else	user = username;    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, PeerChallenge, 16);    SHA1_Update(&sha1Context, rchallenge, 16);    SHA1_Update(&sha1Context, (unsigned char *)user, strlen(user));    SHA1_Final(sha1Hash, &sha1Context);    BCOPY(sha1Hash, Challenge, 8);}/* * Convert the ASCII version of the password to Unicode. * This implicitly supports 8-bit ISO8859/1 characters. * This gives us the little-endian representation, which * is assumed by all M$ CHAP RFCs.  (Unicode byte ordering * is machine-dependent.) */static voidascii2unicode(char ascii[], int ascii_len, u_char unicode[]){    int i;    BZERO(unicode, ascii_len * 2);    for (i = 0; i < ascii_len; i++)	unicode[i * 2] = (u_char) ascii[i];}static voidNTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE]){#ifdef __NetBSD__    /* NetBSD uses the libc md4 routines which take bytes instead of bits */    int			mdlen = secret_len;#else    int			mdlen = secret_len * 8;#endif    MD4_CTX		md4Context;    MD4Init(&md4Context);    /* MD4Update can take at most 64 bytes at a time */    while (mdlen > 512) {	MD4Update(&md4Context, secret, 512);	secret += 64;	mdlen -= 512;    }    MD4Update(&md4Context, secret, mdlen);    MD4Final(hash, &md4Context);}static voidChapMS_NT(u_char *rchallenge, char *secret, int secret_len,	  u_char NTResponse[24]){    u_char	unicodePassword[MAX_NT_PASSWORD * 2];    u_char	PasswordHash[MD4_SIGNATURE_SIZE];    /* Hash the Unicode version of the secret (== password). */    ascii2unicode(secret, secret_len, unicodePassword);    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);    ChallengeResponse(rchallenge, PasswordHash, NTResponse);}static voidChapMS2_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];    ChallengeHash(PeerChallenge, rchallenge, username, Challenge);    /* Hash the Unicode version of the secret (== password). */    ascii2unicode(secret, secret_len, unicodePassword);    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);    ChallengeResponse(Challenge, PasswordHash, NTResponse);}#ifdef MSLANMANstatic u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */static voidChapMS_LANMan(u_char *rchallenge, char *secret, int secret_len,	      unsigned char *response){    int			i;    u_char		UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */    u_char		PasswordHash[MD4_SIGNATURE_SIZE];    /* LANMan password is case insensitive */    BZERO(UcasePassword, sizeof(UcasePassword));    for (i = 0; i < secret_len; i++)       UcasePassword[i] = (u_char)toupper(secret[i]);    (void) DesSetkey(UcasePassword + 0);    DesEncrypt( StdText, PasswordHash + 0 );    (void) DesSetkey(UcasePassword + 7);    DesEncrypt( StdText, PasswordHash + 8 );    ChallengeResponse(rchallenge, PasswordHash, &response[MS_CHAP_LANMANRESP]);}#endifvoidGenerateAuthenticatorResponse(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],			      u_char NTResponse[24], u_char PeerChallenge[16],			      u_char *rchallenge, char *username,			      u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]){    /*     * "Magic" constants used in response generation, from RFC 2759.     */    u_char Magic1[39] = /* "Magic server to client signing constant" */	{ 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,	  0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,	  0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,	  0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 };    u_char Magic2[41] = /* "Pad to make it do more than one iteration" */	{ 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,	  0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,	  0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,	  0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,	  0x6E };    int		i;    SHA1_CTX	sha1Context;    u_char	Digest[SHA1_SIGNATURE_SIZE];    u_char	Challenge[8];    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);    SHA1_Update(&sha1Context, NTResponse, 24);    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));    SHA1_Final(Digest, &sha1Context);    ChallengeHash(PeerChallenge, rchallenge, username, Challenge);    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, Digest, sizeof(Digest));    SHA1_Update(&sha1Context, Challenge, sizeof(Challenge));    SHA1_Update(&sha1Context, Magic2, sizeof(Magic2));    SHA1_Final(Digest, &sha1Context);    /* Convert to ASCII hex string. */    for (i = 0; i < MAX((MS_AUTH_RESPONSE_LENGTH / 2), sizeof(Digest)); i++)	sprintf((char *)&authResponse[i * 2], "%02X", Digest[i]);}static voidGenerateAuthenticatorResponsePlain		(char *secret, int secret_len,		 u_char NTResponse[24], u_char PeerChallenge[16],		 u_char *rchallenge, char *username,		 u_char authResponse[MS_AUTH_RESPONSE_LENGTH+1]){    u_char	unicodePassword[MAX_NT_PASSWORD * 2];    u_char	PasswordHash[MD4_SIGNATURE_SIZE];    u_char	PasswordHashHash[MD4_SIGNATURE_SIZE];    /* Hash (x2) the Unicode version of the secret (== password). */    ascii2unicode(secret, secret_len, unicodePassword);    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);    NTPasswordHash(PasswordHash, sizeof(PasswordHash),		   PasswordHashHash);    GenerateAuthenticatorResponse(PasswordHashHash, NTResponse, PeerChallenge,				  rchallenge, username, authResponse);}#ifdef MPPE/* * Set mppe_xxxx_key from the NTPasswordHashHash. * RFC 2548 (RADIUS support) requires us to export this function (ugh). */voidmppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE]){    SHA1_CTX	sha1Context;    u_char	Digest[SHA1_SIGNATURE_SIZE];	/* >= MPPE_MAX_KEY_LEN */    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);    SHA1_Update(&sha1Context, rchallenge, 8);    SHA1_Final(Digest, &sha1Context);    /* Same key in both directions. */    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));    mppe_keys_set = 1;}/* * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079) */static voidSet_Start_Key(u_char *rchallenge, char *secret, int secret_len){    u_char	unicodePassword[MAX_NT_PASSWORD * 2];    u_char	PasswordHash[MD4_SIGNATURE_SIZE];    u_char	PasswordHashHash[MD4_SIGNATURE_SIZE];    /* Hash (x2) the Unicode version of the secret (== password). */    ascii2unicode(secret, secret_len, unicodePassword);    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);    NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);    mppe_set_keys(rchallenge, PasswordHashHash);}/* * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) * * This helper function used in the Winbind module, which gets the * NTHashHash from the server. */voidmppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],	       u_char NTResponse[24], int IsServer){    SHA1_CTX	sha1Context;    u_char	MasterKey[SHA1_SIGNATURE_SIZE];	/* >= MPPE_MAX_KEY_LEN */    u_char	Digest[SHA1_SIGNATURE_SIZE];	/* >= MPPE_MAX_KEY_LEN */    u_char SHApad1[40] =	{ 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 };    u_char SHApad2[40] =	{ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,	  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,	  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,	  0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 };    /* "This is the MPPE Master Key" */    u_char Magic1[27] =	{ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,	  0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,	  0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 };    /* "On the client side, this is the send key; "       "on the server side, it is the receive key." */    u_char Magic2[84] =	{ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,	  0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,	  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,	  0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,	  0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,	  0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,	  0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,	  0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,	  0x6b, 0x65, 0x79, 0x2e };    /* "On the client side, this is the receive key; "       "on the server side, it is the send key." */    u_char Magic3[84] =	{ 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,	  0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,	  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,	  0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,	  0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,	  0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,	  0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,	  0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,	  0x6b, 0x65, 0x79, 0x2e };    u_char *s;    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);    SHA1_Update(&sha1Context, NTResponse, 24);    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));    SHA1_Final(MasterKey, &sha1Context);    /*     * generate send key     */    if (IsServer)	s = Magic3;    else	s = Magic2;    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, MasterKey, 16);    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));    SHA1_Update(&sha1Context, s, 84);    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));    SHA1_Final(Digest, &sha1Context);    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));    /*     * generate recv key     */    if (IsServer)	s = Magic2;    else	s = Magic3;    SHA1_Init(&sha1Context);    SHA1_Update(&sha1Context, MasterKey, 16);    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));    SHA1_Update(&sha1Context, s, 84);    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));    SHA1_Final(Digest, &sha1Context);    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));    mppe_keys_set = 1;}/* * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079) */static voidSetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer){    u_char	unicodePassword[MAX_NT_PASSWORD * 2];    u_char	PasswordHash[MD4_SIGNATURE_SIZE];    u_char	PasswordHashHash[MD4_SIGNATURE_SIZE];    /* Hash (x2) the Unicode version of the secret (== password). */    ascii2unicode(secret, secret_len, unicodePassword);    NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);    NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);    mppe_set_keys2(PasswordHashHash, NTResponse, IsServer);}#endif /* MPPE */voidChapMS(u_char *rchallenge, char *secret, int secret_len,       unsigned char *response){    BZERO(response, MS_CHAP_RESPONSE_LEN);    ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);#ifdef MSLANMAN    ChapMS_LANMan(rchallenge, secret, secret_len, &response);    /* preferred method is set by option  */    response[MS_CHAP_USENT] = !ms_lanman;#else    response[MS_CHAP_USENT] = 1;#endif#ifdef MPPE    Set_Start_Key(rchallenge, secret, secret_len);#endif}/* * 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). * Do not call with PeerChallenge = response. * * The PeerChallenge field of response is then used for calculation of the * Authenticator Response. */voidChapMS2(u_char *rchallenge, u_char *PeerChallenge,	char *user, char *secret, int secret_len, unsigned char *response,	u_char authResponse[], int authenticator){    /* ARGSUSED */    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)	for (i = 0; i < MS_CHAP2_PEER_CHAL_LEN; i++)	    *p++ = (u_char) (drand48() * 0xff);    else	BCOPY(PeerChallenge, &response[MS_CHAP2_PEER_CHALLENGE],	      MS_CHAP2_PEER_CHAL_LEN);    /* Generate the NT-Response */    ChapMS2_NT(rchallenge, &response[MS_CHAP2_PEER_CHALLENGE], user,	       secret, secret_len, &response[MS_CHAP2_NTRESP]);    /* Generate the Authenticator Response. */    GenerateAuthenticatorResponsePlain(secret, secret_len,				       &response[MS_CHAP2_NTRESP],				       &response[MS_CHAP2_PEER_CHALLENGE],				       rchallenge, user, authResponse);#ifdef MPPE    SetMasterKeys(secret, secret_len,		  &response[MS_CHAP2_NTRESP], authenticator);#endif}#ifdef MPPE/* * Set MPPE options from plugins. */voidset_mppe_enc_types(int policy, int types){    /* Early exit for unknown policies. */    if (policy != MPPE_ENC_POL_ENC_ALLOWED ||	policy != MPPE_ENC_POL_ENC_REQUIRED)	return;    /* Don't modify MPPE if it's optional and wasn't already configured. */    if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)	return;    /*     * Disable undesirable encryption types.  Note that we don't ENABLE     * any encryption types, to avoid overriding manual configuration.     */    switch(types) {	case MPPE_ENC_TYPES_RC4_40:	    ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;	/* disable 128-bit */	    break;	case MPPE_ENC_TYPES_RC4_128:	    ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;	/* disable 40-bit */	    break;	default:	    break;    }}#endif /* MPPE */static struct chap_digest_type chapms_digest = {	CHAP_MICROSOFT,		/* code */	chapms_generate_challenge,	chapms_verify_response,	chapms_make_response,	NULL,			/* check_success */	chapms_handle_failure,};static struct chap_digest_type chapms2_digest = {	CHAP_MICROSOFT_V2,	/* code */	chapms2_generate_challenge,	chapms2_verify_response,	chapms2_make_response,	chapms2_check_success,	chapms_handle_failure,};voidchapms_init(void){	chap_register_digest(&chapms_digest);	chap_register_digest(&chapms2_digest);	//add_options(chapms_option_list);}#endif /* CHAPMS */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?